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 | }; |
167 | typedef uint32_t StateChangeFlags; |
168 | |
169 | RefPtr<Gradient> strokeGradient; |
170 | RefPtr<Pattern> strokePattern; |
171 | |
172 | RefPtr<Gradient> fillGradient; |
173 | RefPtr<Pattern> fillPattern; |
174 | |
175 | FloatSize shadowOffset; |
176 | |
177 | float strokeThickness { 0 }; |
178 | float shadowBlur { 0 }; |
179 | |
180 | TextDrawingModeFlags textDrawingMode { TextModeFill }; |
181 | |
182 | Color strokeColor { Color::black }; |
183 | Color fillColor { Color::black }; |
184 | Color shadowColor; |
185 | |
186 | StrokeStyle strokeStyle { SolidStroke }; |
187 | WindRule fillRule { WindRule::NonZero }; |
188 | |
189 | float alpha { 1 }; |
190 | CompositeOperator compositeOperator { CompositeSourceOver }; |
191 | BlendMode blendMode { BlendMode::Normal }; |
192 | InterpolationQuality imageInterpolationQuality { InterpolationDefault }; |
193 | |
194 | bool shouldAntialias : 1; |
195 | bool shouldSmoothFonts : 1; |
196 | bool shouldSubpixelQuantizeFonts : 1; |
197 | bool shadowsIgnoreTransforms : 1; |
198 | #if USE(CG) |
199 | bool shadowsUseLegacyRadius : 1; |
200 | #endif |
201 | bool drawLuminanceMask : 1; |
202 | }; |
203 | |
204 | struct ImagePaintingOptions { |
205 | ImagePaintingOptions(CompositeOperator compositeOperator = CompositeSourceOver, BlendMode blendMode = BlendMode::Normal, DecodingMode decodingMode = DecodingMode::Synchronous, ImageOrientationDescription orientationDescription = ImageOrientationDescription(), InterpolationQuality interpolationQuality = InterpolationDefault) |
206 | : m_compositeOperator(compositeOperator) |
207 | , m_blendMode(blendMode) |
208 | , m_decodingMode(decodingMode) |
209 | , m_orientationDescription(orientationDescription) |
210 | , m_interpolationQuality(interpolationQuality) |
211 | { |
212 | } |
213 | |
214 | ImagePaintingOptions(ImageOrientationDescription orientationDescription, InterpolationQuality interpolationQuality = InterpolationDefault, CompositeOperator compositeOperator = CompositeSourceOver, BlendMode blendMode = BlendMode::Normal, DecodingMode decodingMode = DecodingMode::Synchronous) |
215 | : m_compositeOperator(compositeOperator) |
216 | , m_blendMode(blendMode) |
217 | , m_decodingMode(decodingMode) |
218 | , m_orientationDescription(orientationDescription) |
219 | , m_interpolationQuality(interpolationQuality) |
220 | { |
221 | } |
222 | |
223 | ImagePaintingOptions(InterpolationQuality interpolationQuality, ImageOrientationDescription orientationDescription = ImageOrientationDescription(), CompositeOperator compositeOperator = CompositeSourceOver, BlendMode blendMode = BlendMode::Normal, DecodingMode decodingMode = DecodingMode::Synchronous) |
224 | : m_compositeOperator(compositeOperator) |
225 | , m_blendMode(blendMode) |
226 | , m_decodingMode(decodingMode) |
227 | , m_orientationDescription(orientationDescription) |
228 | , m_interpolationQuality(interpolationQuality) |
229 | { |
230 | } |
231 | |
232 | bool usesDefaultInterpolation() const { return m_interpolationQuality == InterpolationDefault; } |
233 | |
234 | CompositeOperator m_compositeOperator; |
235 | BlendMode m_blendMode; |
236 | DecodingMode m_decodingMode; |
237 | ImageOrientationDescription m_orientationDescription; |
238 | InterpolationQuality m_interpolationQuality; |
239 | }; |
240 | |
241 | struct GraphicsContextStateChange { |
242 | GraphicsContextStateChange() = default; |
243 | GraphicsContextStateChange(const GraphicsContextState& state, GraphicsContextState::StateChangeFlags flags) |
244 | : m_state(state) |
245 | , m_changeFlags(flags) |
246 | { |
247 | } |
248 | |
249 | GraphicsContextState::StateChangeFlags changesFromState(const GraphicsContextState&) const; |
250 | |
251 | void accumulate(const GraphicsContextState&, GraphicsContextState::StateChangeFlags); |
252 | void apply(GraphicsContext&) const; |
253 | |
254 | void dump(WTF::TextStream&) const; |
255 | |
256 | GraphicsContextState m_state; |
257 | GraphicsContextState::StateChangeFlags m_changeFlags { GraphicsContextState::NoChange }; |
258 | }; |
259 | |
260 | WTF::TextStream& operator<<(WTF::TextStream&, const GraphicsContextStateChange&); |
261 | |
262 | |
263 | class GraphicsContext { |
264 | WTF_MAKE_NONCOPYABLE(GraphicsContext); WTF_MAKE_FAST_ALLOCATED; |
265 | public: |
266 | WEBCORE_EXPORT GraphicsContext(PlatformGraphicsContext*); |
267 | |
268 | using GraphicsContextImplFactory = WTF::Function<std::unique_ptr<GraphicsContextImpl>(GraphicsContext&)>; |
269 | WEBCORE_EXPORT GraphicsContext(const GraphicsContextImplFactory&); |
270 | |
271 | GraphicsContext() = default; |
272 | WEBCORE_EXPORT ~GraphicsContext(); |
273 | |
274 | enum class PaintInvalidationReasons : uint8_t { |
275 | None, |
276 | InvalidatingControlTints, |
277 | InvalidatingImagesWithAsyncDecodes |
278 | }; |
279 | GraphicsContext(PaintInvalidationReasons); |
280 | |
281 | WEBCORE_EXPORT bool hasPlatformContext() const; |
282 | WEBCORE_EXPORT PlatformGraphicsContext* platformContext() const; |
283 | |
284 | bool paintingDisabled() const { return !m_data && !m_impl; } |
285 | bool performingPaintInvalidation() const { return m_paintInvalidationReasons != PaintInvalidationReasons::None; } |
286 | bool invalidatingControlTints() const { return m_paintInvalidationReasons == PaintInvalidationReasons::InvalidatingControlTints; } |
287 | bool invalidatingImagesWithAsyncDecodes() const { return m_paintInvalidationReasons == PaintInvalidationReasons::InvalidatingImagesWithAsyncDecodes; } |
288 | |
289 | WEBCORE_EXPORT void setStrokeThickness(float); |
290 | float strokeThickness() const { return m_state.strokeThickness; } |
291 | |
292 | void setStrokeStyle(StrokeStyle); |
293 | StrokeStyle strokeStyle() const { return m_state.strokeStyle; } |
294 | |
295 | WEBCORE_EXPORT void setStrokeColor(const Color&); |
296 | const Color& strokeColor() const { return m_state.strokeColor; } |
297 | |
298 | void setStrokePattern(Ref<Pattern>&&); |
299 | Pattern* strokePattern() const { return m_state.strokePattern.get(); } |
300 | |
301 | void setStrokeGradient(Ref<Gradient>&&); |
302 | RefPtr<Gradient> strokeGradient() const { return m_state.strokeGradient; } |
303 | |
304 | void setFillRule(WindRule); |
305 | WindRule fillRule() const { return m_state.fillRule; } |
306 | |
307 | WEBCORE_EXPORT void setFillColor(const Color&); |
308 | const Color& fillColor() const { return m_state.fillColor; } |
309 | |
310 | void setFillPattern(Ref<Pattern>&&); |
311 | Pattern* fillPattern() const { return m_state.fillPattern.get(); } |
312 | |
313 | WEBCORE_EXPORT void setFillGradient(Ref<Gradient>&&); |
314 | RefPtr<Gradient> fillGradient() const { return m_state.fillGradient; } |
315 | |
316 | void setShadowsIgnoreTransforms(bool); |
317 | bool shadowsIgnoreTransforms() const { return m_state.shadowsIgnoreTransforms; } |
318 | |
319 | WEBCORE_EXPORT void setShouldAntialias(bool); |
320 | bool shouldAntialias() const { return m_state.shouldAntialias; } |
321 | |
322 | WEBCORE_EXPORT void setShouldSmoothFonts(bool); |
323 | bool shouldSmoothFonts() const { return m_state.shouldSmoothFonts; } |
324 | |
325 | // Normally CG enables subpixel-quantization because it improves the performance of aligning glyphs. |
326 | // In some cases we have to disable to to ensure a high-quality output of the glyphs. |
327 | void setShouldSubpixelQuantizeFonts(bool); |
328 | bool shouldSubpixelQuantizeFonts() const { return m_state.shouldSubpixelQuantizeFonts; } |
329 | |
330 | const GraphicsContextState& state() const { return m_state; } |
331 | |
332 | #if USE(CG) || USE(DIRECT2D) || USE(CAIRO) |
333 | WEBCORE_EXPORT void drawNativeImage(const NativeImagePtr&, const FloatSize& selfSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, BlendMode = BlendMode::Normal, ImageOrientation = ImageOrientation()); |
334 | #endif |
335 | |
336 | #if USE(CG) || USE(DIRECT2D) |
337 | void applyStrokePattern(); |
338 | void applyFillPattern(); |
339 | void drawPath(const Path&); |
340 | |
341 | WEBCORE_EXPORT void setIsCALayerContext(bool); |
342 | bool isCALayerContext() const; |
343 | |
344 | WEBCORE_EXPORT void setIsAcceleratedContext(bool); |
345 | #endif |
346 | bool isAcceleratedContext() const; |
347 | RenderingMode renderingMode() const { return isAcceleratedContext() ? Accelerated : Unaccelerated; } |
348 | |
349 | WEBCORE_EXPORT void save(); |
350 | WEBCORE_EXPORT void restore(); |
351 | |
352 | // These draw methods will do both stroking and filling. |
353 | // FIXME: ...except drawRect(), which fills properly but always strokes |
354 | // using a 1-pixel stroke inset from the rect borders (of the correct |
355 | // stroke color). |
356 | void drawRect(const FloatRect&, float borderThickness = 1); |
357 | void drawLine(const FloatPoint&, const FloatPoint&); |
358 | |
359 | void drawEllipse(const FloatRect&); |
360 | void drawRaisedEllipse(const FloatRect&, const Color& ellipseColor, const Color& shadowColor); |
361 | |
362 | WEBCORE_EXPORT void fillPath(const Path&); |
363 | WEBCORE_EXPORT void strokePath(const Path&); |
364 | |
365 | void fillEllipse(const FloatRect&); |
366 | void strokeEllipse(const FloatRect&); |
367 | |
368 | WEBCORE_EXPORT void fillRect(const FloatRect&); |
369 | WEBCORE_EXPORT void fillRect(const FloatRect&, const Color&); |
370 | void fillRect(const FloatRect&, Gradient&); |
371 | void fillRect(const FloatRect&, const Color&, CompositeOperator, BlendMode = BlendMode::Normal); |
372 | void fillRoundedRect(const FloatRoundedRect&, const Color&, BlendMode = BlendMode::Normal); |
373 | void fillRectWithRoundedHole(const FloatRect&, const FloatRoundedRect& roundedHoleRect, const Color&); |
374 | |
375 | WEBCORE_EXPORT void clearRect(const FloatRect&); |
376 | |
377 | WEBCORE_EXPORT void strokeRect(const FloatRect&, float lineWidth); |
378 | |
379 | WEBCORE_EXPORT ImageDrawResult drawImage(Image&, const FloatPoint& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
380 | WEBCORE_EXPORT ImageDrawResult drawImage(Image&, const FloatRect& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
381 | ImageDrawResult drawImage(Image&, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& = ImagePaintingOptions()); |
382 | |
383 | ImageDrawResult drawTiledImage(Image&, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& = ImagePaintingOptions()); |
384 | ImageDrawResult drawTiledImage(Image&, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor, |
385 | Image::TileRule, Image::TileRule, const ImagePaintingOptions& = ImagePaintingOptions()); |
386 | |
387 | WEBCORE_EXPORT void drawImageBuffer(ImageBuffer&, const FloatPoint& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
388 | void drawImageBuffer(ImageBuffer&, const FloatRect& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
389 | void drawImageBuffer(ImageBuffer&, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& = ImagePaintingOptions()); |
390 | |
391 | void drawPattern(Image&, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform&, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator, BlendMode = BlendMode::Normal); |
392 | |
393 | WEBCORE_EXPORT void drawConsumingImageBuffer(std::unique_ptr<ImageBuffer>, const FloatPoint& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
394 | void drawConsumingImageBuffer(std::unique_ptr<ImageBuffer>, const FloatRect& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
395 | void drawConsumingImageBuffer(std::unique_ptr<ImageBuffer>, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& = ImagePaintingOptions()); |
396 | |
397 | WEBCORE_EXPORT void setImageInterpolationQuality(InterpolationQuality); |
398 | InterpolationQuality imageInterpolationQuality() const { return m_state.imageInterpolationQuality; } |
399 | |
400 | WEBCORE_EXPORT void clip(const FloatRect&); |
401 | void clipRoundedRect(const FloatRoundedRect&); |
402 | |
403 | void clipOut(const FloatRect&); |
404 | void clipOutRoundedRect(const FloatRoundedRect&); |
405 | void clipPath(const Path&, WindRule = WindRule::EvenOdd); |
406 | void clipToImageBuffer(ImageBuffer&, const FloatRect&); |
407 | |
408 | IntRect clipBounds() const; |
409 | |
410 | void setTextDrawingMode(TextDrawingModeFlags); |
411 | TextDrawingModeFlags textDrawingMode() const { return m_state.textDrawingMode; } |
412 | |
413 | float drawText(const FontCascade&, const TextRun&, const FloatPoint&, unsigned from = 0, Optional<unsigned> to = WTF::nullopt); |
414 | void drawGlyphs(const Font&, const GlyphBuffer&, unsigned from, unsigned numGlyphs, const FloatPoint&, FontSmoothingMode); |
415 | void drawEmphasisMarks(const FontCascade&, const TextRun&, const AtomicString& mark, const FloatPoint&, unsigned from = 0, Optional<unsigned> to = WTF::nullopt); |
416 | void drawBidiText(const FontCascade&, const TextRun&, const FloatPoint&, FontCascade::CustomFontNotReadyAction = FontCascade::DoNotPaintIfFontNotReady); |
417 | |
418 | void applyState(const GraphicsContextState&); |
419 | |
420 | enum RoundingMode { |
421 | RoundAllSides, |
422 | RoundOriginAndDimensions |
423 | }; |
424 | FloatRect roundToDevicePixels(const FloatRect&, RoundingMode = RoundAllSides); |
425 | |
426 | FloatRect computeUnderlineBoundsForText(const FloatRect&, bool printing); |
427 | WEBCORE_EXPORT void drawLineForText(const FloatRect&, bool printing, bool doubleLines = false, StrokeStyle = SolidStroke); |
428 | void drawLinesForText(const FloatPoint&, float thickness, const DashArray& widths, bool printing, bool doubleLines = false, StrokeStyle = SolidStroke); |
429 | void drawDotsForDocumentMarker(const FloatRect&, DocumentMarkerLineStyle); |
430 | |
431 | WEBCORE_EXPORT void beginTransparencyLayer(float opacity); |
432 | WEBCORE_EXPORT void endTransparencyLayer(); |
433 | bool isInTransparencyLayer() const { return (m_transparencyCount > 0) && supportsTransparencyLayers(); } |
434 | |
435 | WEBCORE_EXPORT void setShadow(const FloatSize&, float blur, const Color&); |
436 | // Legacy shadow blur radius is used for canvas, and -webkit-box-shadow. |
437 | // It has different treatment of radii > 8px. |
438 | void setLegacyShadow(const FloatSize&, float blur, const Color&); |
439 | |
440 | WEBCORE_EXPORT void clearShadow(); |
441 | bool getShadow(FloatSize&, float&, Color&) const; |
442 | |
443 | bool hasVisibleShadow() const { return m_state.shadowColor.isVisible(); } |
444 | bool hasShadow() const { return hasVisibleShadow() && (m_state.shadowBlur || m_state.shadowOffset.width() || m_state.shadowOffset.height()); } |
445 | bool hasBlurredShadow() const { return hasVisibleShadow() && m_state.shadowBlur; } |
446 | |
447 | void drawFocusRing(const Vector<FloatRect>&, float width, float offset, const Color&); |
448 | void drawFocusRing(const Path&, float width, float offset, const Color&); |
449 | #if PLATFORM(MAC) |
450 | void drawFocusRing(const Path&, double timeOffset, bool& needsRedraw, const Color&); |
451 | void drawFocusRing(const Vector<FloatRect>&, double timeOffset, bool& needsRedraw, const Color&); |
452 | #endif |
453 | |
454 | void setLineCap(LineCap); |
455 | void setLineDash(const DashArray&, float dashOffset); |
456 | void setLineJoin(LineJoin); |
457 | void setMiterLimit(float); |
458 | |
459 | void setAlpha(float); |
460 | float alpha() const { return m_state.alpha; } |
461 | |
462 | WEBCORE_EXPORT void setCompositeOperation(CompositeOperator, BlendMode = BlendMode::Normal); |
463 | CompositeOperator compositeOperation() const { return m_state.compositeOperator; } |
464 | BlendMode blendModeOperation() const { return m_state.blendMode; } |
465 | |
466 | void setDrawLuminanceMask(bool); |
467 | bool drawLuminanceMask() const { return m_state.drawLuminanceMask; } |
468 | |
469 | // This clip function is used only by <canvas> code. It allows |
470 | // implementations to handle clipping on the canvas differently since |
471 | // the discipline is different. |
472 | void canvasClip(const Path&, WindRule = WindRule::EvenOdd); |
473 | void clipOut(const Path&); |
474 | |
475 | void scale(float s) |
476 | { |
477 | scale({ s, s }); |
478 | } |
479 | WEBCORE_EXPORT void scale(const FloatSize&); |
480 | void rotate(float angleInRadians); |
481 | void translate(const FloatSize& size) { translate(size.width(), size.height()); } |
482 | void translate(const FloatPoint& p) { translate(p.x(), p.y()); } |
483 | WEBCORE_EXPORT void translate(float x, float y); |
484 | |
485 | void setURLForRect(const URL&, const FloatRect&); |
486 | |
487 | void setDestinationForRect(const String& name, const FloatRect&); |
488 | void addDestinationAtPoint(const String& name, const FloatPoint&); |
489 | |
490 | void concatCTM(const AffineTransform&); |
491 | void setCTM(const AffineTransform&); |
492 | |
493 | enum IncludeDeviceScale { DefinitelyIncludeDeviceScale, PossiblyIncludeDeviceScale }; |
494 | AffineTransform getCTM(IncludeDeviceScale includeScale = PossiblyIncludeDeviceScale) const; |
495 | |
496 | // This function applies the device scale factor to the context, making the context capable of |
497 | // acting as a base-level context for a HiDPI environment. |
498 | WEBCORE_EXPORT void applyDeviceScaleFactor(float); |
499 | void platformApplyDeviceScaleFactor(float); |
500 | FloatSize scaleFactor() const; |
501 | FloatSize scaleFactorForDrawing(const FloatRect& destRect, const FloatRect& srcRect) const; |
502 | |
503 | #if OS(WINDOWS) |
504 | HDC getWindowsContext(const IntRect&, bool supportAlphaBlend); // The passed in rect is used to create a bitmap for compositing inside transparency layers. |
505 | void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend); // The passed in HDC should be the one handed back by getWindowsContext. |
506 | HDC hdc() const; |
507 | #if PLATFORM(WIN) |
508 | #if USE(WINGDI) |
509 | const AffineTransform& affineTransform() const; |
510 | AffineTransform& affineTransform(); |
511 | void resetAffineTransform(); |
512 | void fillRect(const FloatRect&, const Gradient*); |
513 | void drawText(const Font&, const GlyphBuffer&, int from, int numGlyphs, const FloatPoint&); |
514 | void drawFrameControl(const IntRect& rect, unsigned type, unsigned state); |
515 | void drawFocusRect(const IntRect& rect); |
516 | void paintTextField(const IntRect& rect, unsigned state); |
517 | void drawBitmap(SharedBitmap*, const IntRect& dstRect, const IntRect& srcRect, CompositeOperator, BlendMode); |
518 | void drawBitmapPattern(SharedBitmap*, const FloatRect& tileRectIn, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& destRect, const IntSize& origSourceSize); |
519 | void drawIcon(HICON icon, const IntRect& dstRect, UINT flags); |
520 | void drawRoundCorner(bool newClip, RECT clipRect, RECT rectWin, HDC dc, int width, int height); |
521 | #else |
522 | GraphicsContext(HDC, bool hasAlpha = false); // FIXME: To be removed. |
523 | |
524 | // When set to true, child windows should be rendered into this context |
525 | // rather than allowing them just to render to the screen. Defaults to |
526 | // false. |
527 | // FIXME: This is a layering violation. GraphicsContext shouldn't know |
528 | // what a "window" is. It would be much more appropriate for this flag |
529 | // to be passed as a parameter alongside the GraphicsContext, but doing |
530 | // that would require lots of changes in cross-platform code that we |
531 | // aren't sure we want to make. |
532 | void setShouldIncludeChildWindows(bool); |
533 | bool shouldIncludeChildWindows() const; |
534 | |
535 | class WindowsBitmap { |
536 | WTF_MAKE_NONCOPYABLE(WindowsBitmap); |
537 | public: |
538 | WindowsBitmap(HDC, const IntSize&); |
539 | ~WindowsBitmap(); |
540 | |
541 | HDC hdc() const { return m_hdc; } |
542 | UInt8* buffer() const { return m_pixelData.buffer(); } |
543 | unsigned bufferLength() const { return m_pixelData.bufferLength(); } |
544 | const IntSize& size() const { return m_pixelData.size(); } |
545 | unsigned bytesPerRow() const { return m_pixelData.bytesPerRow(); } |
546 | unsigned short bitsPerPixel() const { return m_pixelData.bitsPerPixel(); } |
547 | const DIBPixelData& windowsDIB() const { return m_pixelData; } |
548 | |
549 | private: |
550 | HDC m_hdc; |
551 | HBITMAP m_bitmap; |
552 | DIBPixelData m_pixelData; |
553 | }; |
554 | |
555 | std::unique_ptr<WindowsBitmap> createWindowsBitmap(const IntSize&); |
556 | // The bitmap should be non-premultiplied. |
557 | void drawWindowsBitmap(WindowsBitmap*, const IntPoint&); |
558 | #endif |
559 | #if USE(DIRECT2D) |
560 | GraphicsContext(HDC, ID2D1DCRenderTarget**, RECT, bool hasAlpha = false); // FIXME: To be removed. |
561 | |
562 | WEBCORE_EXPORT static ID2D1Factory* systemFactory(); |
563 | WEBCORE_EXPORT static ID2D1RenderTarget* defaultRenderTarget(); |
564 | |
565 | WEBCORE_EXPORT void beginDraw(); |
566 | D2D1_COLOR_F colorWithGlobalAlpha(const Color&) const; |
567 | WEBCORE_EXPORT void endDraw(); |
568 | void flush(); |
569 | |
570 | ID2D1Brush* solidStrokeBrush() const; |
571 | ID2D1Brush* solidFillBrush() const; |
572 | ID2D1Brush* patternStrokeBrush() const; |
573 | ID2D1Brush* patternFillBrush() const; |
574 | ID2D1StrokeStyle* platformStrokeStyle() const; |
575 | |
576 | ID2D1SolidColorBrush* brushWithColor(const Color&); |
577 | #endif |
578 | #else // PLATFORM(WIN) |
579 | bool shouldIncludeChildWindows() const { return false; } |
580 | #endif // PLATFORM(WIN) |
581 | #endif // OS(WINDOWS) |
582 | |
583 | static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle); |
584 | |
585 | bool supportsInternalLinks() const; |
586 | |
587 | private: |
588 | void platformInit(PlatformGraphicsContext*); |
589 | void platformDestroy(); |
590 | |
591 | #if PLATFORM(WIN) && !USE(WINGDI) |
592 | void platformInit(HDC, bool hasAlpha = false); |
593 | #endif |
594 | |
595 | #if USE(DIRECT2D) |
596 | void platformInit(HDC, ID2D1RenderTarget**, RECT, bool hasAlpha = false); |
597 | void drawWithoutShadow(const FloatRect& boundingRect, const WTF::Function<void(ID2D1RenderTarget*)>&); |
598 | void drawWithShadow(const FloatRect& boundingRect, const WTF::Function<void(ID2D1RenderTarget*)>&); |
599 | #endif |
600 | |
601 | void savePlatformState(); |
602 | void restorePlatformState(); |
603 | |
604 | void setPlatformTextDrawingMode(TextDrawingModeFlags); |
605 | |
606 | void setPlatformStrokeColor(const Color&); |
607 | void setPlatformStrokeStyle(StrokeStyle); |
608 | void setPlatformStrokeThickness(float); |
609 | |
610 | void setPlatformFillColor(const Color&); |
611 | |
612 | void setPlatformShouldAntialias(bool); |
613 | void setPlatformShouldSmoothFonts(bool); |
614 | void setPlatformImageInterpolationQuality(InterpolationQuality); |
615 | |
616 | void setPlatformShadow(const FloatSize&, float blur, const Color&); |
617 | void clearPlatformShadow(); |
618 | |
619 | void setPlatformAlpha(float); |
620 | void setPlatformCompositeOperation(CompositeOperator, BlendMode = BlendMode::Normal); |
621 | |
622 | void beginPlatformTransparencyLayer(float opacity); |
623 | void endPlatformTransparencyLayer(); |
624 | static bool supportsTransparencyLayers(); |
625 | |
626 | void fillEllipseAsPath(const FloatRect&); |
627 | void strokeEllipseAsPath(const FloatRect&); |
628 | |
629 | void platformFillEllipse(const FloatRect&); |
630 | void platformStrokeEllipse(const FloatRect&); |
631 | |
632 | void platformFillRoundedRect(const FloatRoundedRect&, const Color&); |
633 | |
634 | FloatRect computeLineBoundsAndAntialiasingModeForText(const FloatRect&, bool printing, Color&); |
635 | |
636 | float dashedLineCornerWidthForStrokeWidth(float) const; |
637 | float dashedLinePatternWidthForStrokeWidth(float) const; |
638 | float dashedLinePatternOffsetForPatternAndStrokeWidth(float patternWidth, float strokeWidth) const; |
639 | Vector<FloatPoint> centerLineAndCutOffCorners(bool isVerticalLine, float cornerWidth, FloatPoint point1, FloatPoint point2) const; |
640 | |
641 | GraphicsContextPlatformPrivate* m_data { nullptr }; |
642 | std::unique_ptr<GraphicsContextImpl> m_impl; |
643 | |
644 | GraphicsContextState m_state; |
645 | Vector<GraphicsContextState, 1> m_stack; |
646 | |
647 | const PaintInvalidationReasons m_paintInvalidationReasons { PaintInvalidationReasons::None }; |
648 | unsigned m_transparencyCount { 0 }; |
649 | }; |
650 | |
651 | class GraphicsContextStateSaver { |
652 | WTF_MAKE_FAST_ALLOCATED; |
653 | public: |
654 | GraphicsContextStateSaver(GraphicsContext& context, bool saveAndRestore = true) |
655 | : m_context(context) |
656 | , m_saveAndRestore(saveAndRestore) |
657 | { |
658 | if (m_saveAndRestore) |
659 | m_context.save(); |
660 | } |
661 | |
662 | ~GraphicsContextStateSaver() |
663 | { |
664 | if (m_saveAndRestore) |
665 | m_context.restore(); |
666 | } |
667 | |
668 | void save() |
669 | { |
670 | ASSERT(!m_saveAndRestore); |
671 | m_context.save(); |
672 | m_saveAndRestore = true; |
673 | } |
674 | |
675 | void restore() |
676 | { |
677 | ASSERT(m_saveAndRestore); |
678 | m_context.restore(); |
679 | m_saveAndRestore = false; |
680 | } |
681 | |
682 | GraphicsContext* context() const { return &m_context; } |
683 | |
684 | private: |
685 | GraphicsContext& m_context; |
686 | bool m_saveAndRestore; |
687 | }; |
688 | |
689 | class InterpolationQualityMaintainer { |
690 | public: |
691 | explicit InterpolationQualityMaintainer(GraphicsContext& graphicsContext, InterpolationQuality interpolationQualityToUse) |
692 | : m_graphicsContext(graphicsContext) |
693 | , m_currentInterpolationQuality(graphicsContext.imageInterpolationQuality()) |
694 | , m_interpolationQualityChanged(interpolationQualityToUse != InterpolationDefault && m_currentInterpolationQuality != interpolationQualityToUse) |
695 | { |
696 | if (m_interpolationQualityChanged) |
697 | m_graphicsContext.setImageInterpolationQuality(interpolationQualityToUse); |
698 | } |
699 | |
700 | explicit InterpolationQualityMaintainer(GraphicsContext& graphicsContext, Optional<InterpolationQuality> interpolationQuality) |
701 | : InterpolationQualityMaintainer(graphicsContext, interpolationQuality ? interpolationQuality.value() : graphicsContext.imageInterpolationQuality()) |
702 | { |
703 | } |
704 | |
705 | ~InterpolationQualityMaintainer() |
706 | { |
707 | if (m_interpolationQualityChanged) |
708 | m_graphicsContext.setImageInterpolationQuality(m_currentInterpolationQuality); |
709 | } |
710 | |
711 | private: |
712 | GraphicsContext& m_graphicsContext; |
713 | InterpolationQuality m_currentInterpolationQuality; |
714 | bool m_interpolationQualityChanged; |
715 | }; |
716 | |
717 | } // namespace WebCore |
718 | |