LibreOffice Module vcl (master)  1
gdiimpl.hxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_VCL_SKIA_GDIIMPL_HXX
21 #define INCLUDED_VCL_SKIA_GDIIMPL_HXX
22 
23 #include <vcl/dllapi.h>
24 
25 #include <salgdiimpl.hxx>
26 #include <salgeom.hxx>
27 
28 #include <SkSurface.h>
29 #include <SkRegion.h>
30 
31 #include <prewin.h>
32 #include <tools/sk_app/WindowContext.h>
33 #include <postwin.h>
34 
35 class SkiaFlushIdle;
36 class GenericSalLayout;
37 class SkFont;
38 class SkiaSalBitmap;
39 
41 {
42 public:
44  virtual ~SkiaSalGraphicsImpl() override;
45 
46  virtual void Init() override;
47 
48  virtual void DeInit() override;
49 
50  virtual OUString getRenderBackendName() const override { return "skia"; }
51 
52  const vcl::Region& getClipRegion() const;
53  virtual bool setClipRegion(const vcl::Region&) override;
54 
55  //
56  // get the depth of the device
57  virtual sal_uInt16 GetBitCount() const override;
58 
59  // get the width of the device
60  virtual tools::Long GetGraphicsWidth() const override;
61 
62  // set the clip region to empty
63  virtual void ResetClipRegion() override;
64 
65  // set the line color to transparent (= don't draw lines)
66 
67  virtual void SetLineColor() override;
68 
69  // set the line color to a specific color
70  virtual void SetLineColor(Color nColor) override;
71 
72  // set the fill color to transparent (= don't fill)
73  virtual void SetFillColor() override;
74 
75  // set the fill color to a specific color, shapes will be
76  // filled accordingly
77  virtual void SetFillColor(Color nColor) override;
78 
79  // enable/disable XOR drawing
80  virtual void SetXORMode(bool bSet, bool bInvertOnly) override;
81 
82  // set line color for raster operations
83  virtual void SetROPLineColor(SalROPColor nROPColor) override;
84 
85  // set fill color for raster operations
86  virtual void SetROPFillColor(SalROPColor nROPColor) override;
87 
88  // draw --> LineColor and FillColor and RasterOp and ClipRegion
89  virtual void drawPixel(tools::Long nX, tools::Long nY) override;
90  virtual void drawPixel(tools::Long nX, tools::Long nY, Color nColor) override;
91 
92  virtual void drawLine(tools::Long nX1, tools::Long nY1, tools::Long nX2,
93  tools::Long nY2) override;
94 
95  virtual void drawRect(tools::Long nX, tools::Long nY, tools::Long nWidth,
96  tools::Long nHeight) override;
97 
98  virtual void drawPolyLine(sal_uInt32 nPoints, const Point* pPtAry) override;
99 
100  virtual void drawPolygon(sal_uInt32 nPoints, const Point* pPtAry) override;
101 
102  virtual void drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32* pPoints,
103  const Point** pPtAry) override;
104 
105  virtual bool drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectToDevice,
106  const basegfx::B2DPolyPolygon&, double fTransparency) override;
107 
108  virtual bool drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice,
109  const basegfx::B2DPolygon&, double fTransparency, double fLineWidth,
110  const std::vector<double>* pStroke, basegfx::B2DLineJoin,
111  css::drawing::LineCap, double fMiterMinimumAngle,
112  bool bPixelSnapHairline) override;
113 
114  virtual bool drawPolyLineBezier(sal_uInt32 nPoints, const Point* pPtAry,
115  const PolyFlags* pFlgAry) override;
116 
117  virtual bool drawPolygonBezier(sal_uInt32 nPoints, const Point* pPtAry,
118  const PolyFlags* pFlgAry) override;
119 
120  virtual bool drawPolyPolygonBezier(sal_uInt32 nPoly, const sal_uInt32* pPoints,
121  const Point* const* pPtAry,
122  const PolyFlags* const* pFlgAry) override;
123 
124  // CopyArea --> No RasterOp, but ClipRegion
125  virtual void copyArea(tools::Long nDestX, tools::Long nDestY, tools::Long nSrcX,
126  tools::Long nSrcY, tools::Long nSrcWidth, tools::Long nSrcHeight,
127  bool bWindowInvalidate) override;
128 
129  virtual void copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics) override;
130 
131  virtual bool blendBitmap(const SalTwoRect&, const SalBitmap& rBitmap) override;
132 
133  virtual bool blendAlphaBitmap(const SalTwoRect&, const SalBitmap& rSrcBitmap,
134  const SalBitmap& rMaskBitmap,
135  const SalBitmap& rAlphaBitmap) override;
136 
137  virtual void drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap) override;
138 
139  virtual void drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap,
140  const SalBitmap& rMaskBitmap) override;
141 
142  virtual void drawMask(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap,
143  Color nMaskColor) override;
144 
145  virtual std::shared_ptr<SalBitmap> getBitmap(tools::Long nX, tools::Long nY, tools::Long nWidth,
146  tools::Long nHeight) override;
147 
148  virtual Color getPixel(tools::Long nX, tools::Long nY) override;
149 
150  // invert --> ClipRegion (only Windows or VirDevs)
151  virtual void invert(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
152  SalInvert nFlags) override;
153 
154  virtual void invert(sal_uInt32 nPoints, const Point* pPtAry, SalInvert nFlags) override;
155 
156  virtual bool drawEPS(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
157  void* pPtr, sal_uInt32 nSize) override;
158 
171  virtual bool drawAlphaBitmap(const SalTwoRect&, const SalBitmap& rSourceBitmap,
172  const SalBitmap& rAlphaBitmap) override;
173 
175  virtual bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
176  const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
177  const SalBitmap* pAlphaBitmap, double fAlpha) override;
178 
179  virtual bool hasFastDrawTransformedBitmap() const override;
180 
196  virtual bool drawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth,
197  tools::Long nHeight, sal_uInt8 nTransparency) override;
198 
199  virtual bool drawGradient(const tools::PolyPolygon& rPolygon,
200  const Gradient& rGradient) override;
201  virtual bool implDrawGradient(const basegfx::B2DPolyPolygon& rPolyPolygon,
202  const SalGradient& rGradient) override;
203 
204  virtual bool supportsOperation(OutDevSupportType eType) const override;
205 
206 #ifdef DBG_UTIL
207  void dump(const char* file) const;
208 #endif
209 
210  // Default blend mode for SkPaint is SkBlendMode::kSrcOver
211  void drawBitmap(const SalTwoRect& rPosAry, const SkiaSalBitmap& bitmap,
212  SkBlendMode blendMode = SkBlendMode::kSrcOver);
213 
214  void drawImage(const SalTwoRect& rPosAry, const sk_sp<SkImage>& aImage,
215  SkBlendMode eBlendMode = SkBlendMode::kSrcOver);
216 
217  void drawShader(const SalTwoRect& rPosAry, const sk_sp<SkShader>& shader,
218  SkBlendMode blendMode = SkBlendMode::kSrcOver);
219 
220  enum class GlyphOrientation
221  {
222  Apply,
223  Ignore
224  };
225  void drawGenericLayout(const GenericSalLayout& layout, Color textColor, const SkFont& font,
226  GlyphOrientation glyphOrientation);
227 
228 protected:
229  // To be called before any drawing.
230  void preDraw();
231  // To be called after any drawing.
232  void postDraw();
233  // The canvas to draw to. Will be diverted to a temporary for Xor mode.
234  SkCanvas* getDrawCanvas() { return mXorMode ? getXorCanvas() : mSurface->getCanvas(); }
235  // Call before makeImageSnapshot(), ensures the content is up to date.
236  void flushDrawing();
237 
238  virtual void createSurface();
239  // Call to ensure that mSurface is valid. If mSurface is going to be modified,
240  // use preDraw() instead of this.
241  void checkSurface();
242  void destroySurface();
243  // Reimplemented for X11.
244  virtual bool avoidRecreateByResize() const;
245  void createWindowSurface(bool forceRaster = false);
246  virtual void createWindowContext(bool forceRaster = false) = 0;
247  void createOffscreenSurface();
248 
249  void privateDrawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth,
250  tools::Long nHeight, double nTransparency, bool blockAA = false);
251 
252  void setProvider(SalGeometryProvider* provider) { mProvider = provider; }
253 
254  bool isOffscreen() const;
255  bool isGPU() const { return mIsGPU; }
256 
257  void invert(basegfx::B2DPolygon const& rPoly, SalInvert eFlags);
258 
259  // Called by SkiaFlushIdle.
260  virtual void performFlush() = 0;
261  void scheduleFlush();
262  friend class SkiaFlushIdle;
263 
264  // get the width of the device
265  int GetWidth() const { return mProvider ? mProvider->GetWidth() : 1; }
266  // get the height of the device
267  int GetHeight() const { return mProvider ? mProvider->GetHeight() : 1; }
268 
269  SkCanvas* getXorCanvas();
270  void applyXor();
271  // NOTE: This must be called before the operation does any drawing.
272  void addUpdateRegion(const SkRect& rect)
273  {
274  // Make slightly larger, just in case (rounding, antialiasing,...).
275  SkIRect addedRect = rect.makeOutset(2, 2).round();
276  if (mXorMode)
277  {
278  // Two xor operations should cancel each other out. We batch xor operations,
279  // but if they can overlap, apply xor now, since applyXor() does the operation
280  // just once.
281  if (mXorRegion.intersects(addedRect))
282  applyXor();
283  mXorRegion.op(addedRect, SkRegion::kUnion_Op);
284  }
285  // Using SkIRect should be enough, SkRegion would be too slow with many operations
286  // and swapping to the screen is not _that_slow.
287  mDirtyRect.join(addedRect);
288  }
289  static void setCanvasClipRegion(SkCanvas* canvas, const vcl::Region& region);
290  sk_sp<SkImage> mergeCacheBitmaps(const SkiaSalBitmap& bitmap, const SkiaSalBitmap* alphaBitmap,
291  const Size targetSize);
292 
293  // Skia uses floating point coordinates, so when we use integer coordinates, sometimes
294  // rounding results in off-by-one errors (down), especially when drawing using GPU,
295  // see https://bugs.chromium.org/p/skia/issues/detail?id=9611 . Compensate for
296  // it by using centers of pixels. Using 0.5 may sometimes round up, so go with 0.495 .
297  static constexpr SkScalar toSkX(tools::Long x) { return x + 0.495; }
298  static constexpr SkScalar toSkY(tools::Long y) { return y + 0.495; }
299  // Value to add to be exactly in the middle of the pixel.
300  static constexpr SkScalar toSkXYFix = SkScalar(0.005);
301 
302  // Perform any pending drawing such as delayed merging of polygons. Called by preDraw()
303  // and anything that means the next operation cannot be another one in a series (e.g.
304  // changing colors).
305  void checkPendingDrawing();
306  bool delayDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double transparency);
307  void performDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double transparency,
308  bool useAA);
309 
310  template <typename charT, typename traits>
311  friend inline std::basic_ostream<charT, traits>&
312  operator<<(std::basic_ostream<charT, traits>& stream, const SkiaSalGraphicsImpl* graphics)
313  {
314  if (graphics == nullptr)
315  return stream << "(null)";
316  // O - offscreen, G - GPU-based, R - raster
317  return stream << static_cast<const void*>(graphics) << " "
318  << Size(graphics->GetWidth(), graphics->GetHeight())
319  << (graphics->isGPU() ? "G" : "R") << (graphics->isOffscreen() ? "O" : "");
320  }
321 
325  std::unique_ptr<sk_app::WindowContext> mWindowContext;
326  // The Skia surface that is target of all the rendering.
327  sk_sp<SkSurface> mSurface;
328  bool mIsGPU; // whether the surface is GPU-backed
329  SkIRect mDirtyRect; // the area that has been changed since the last performFlush()
333  bool mXorMode;
334  SkBitmap mXorBitmap;
335  std::unique_ptr<SkCanvas> mXorCanvas;
336  SkRegion mXorRegion; // the area that needs updating for the xor operation
337  std::unique_ptr<SkiaFlushIdle> mFlush;
338  // Info about pending polygons to draw (we try to merge adjacent polygons into one).
340  {
343  double transparency;
344  };
347 };
348 
349 #endif
350 
351 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Interface used to share logic on sizing between SalVirtualDevices and SalFrames.
Definition: salgeom.hxx:63
vcl::Region mClipRegion
Definition: gdiimpl.hxx:330
SalGeometryProvider * mProvider
Pointer to the SalFrame or SalVirtualDevice.
Definition: gdiimpl.hxx:324
virtual void drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32 *pPoints, const Point **pPtAry)=0
virtual void drawPolygon(sal_uInt32 nPoints, const Point *pPtAry)=0
virtual void drawBitmap(const SalTwoRect &rPosAry, const SalBitmap &rSalBitmap)=0
SalROPColor
Definition: salgtype.hxx:71
virtual bool drawAlphaBitmap(const SalTwoRect &, const SalBitmap &rSourceBitmap, const SalBitmap &rAlphaBitmap)=0
virtual void copyBits(const SalTwoRect &rPosAry, SalGraphics *pSrcGraphics)=0
int GetWidth() const
Definition: gdiimpl.hxx:265
virtual void SetXORMode(bool bSet, bool bInvertOnly)=0
#define VCL_DLLPUBLIC
Definition: dllapi.h:29
long Long
virtual void copyArea(tools::Long nDestX, tools::Long nDestY, tools::Long nSrcX, tools::Long nSrcY, tools::Long nSrcWidth, tools::Long nSrcHeight, bool bWindowInvalidate)=0
virtual bool supportsOperation(OutDevSupportType eType) const =0
std::unique_ptr< SkiaFlushIdle > mFlush
Definition: gdiimpl.hxx:337
OutDevSupportType
Definition: vclenum.hxx:196
virtual void drawRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight)=0
SalGraphics & mParent
Definition: gdiimpl.hxx:322
virtual bool drawGradient(const tools::PolyPolygon &rPolygon, const Gradient &rGradient)=0
virtual bool blendBitmap(const SalTwoRect &, const SalBitmap &rBitmap)=0
std::unique_ptr< SkCanvas > mXorCanvas
Definition: gdiimpl.hxx:335
virtual void SetLineColor()=0
virtual void drawLine(tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2)=0
virtual bool implDrawGradient(basegfx::B2DPolyPolygon const &rPolyPolygon, SalGradient const &rGradient)=0
virtual tools::Long GetGraphicsWidth() const =0
int mPendingOperationsToFlush
Definition: gdiimpl.hxx:346
virtual bool hasFastDrawTransformedBitmap() const =0
Used e.g.
virtual void DeInit()
Definition: salgdiimpl.hxx:49
basegfx::B2DPolyPolygonVector polygons
Definition: gdiimpl.hxx:341
LastPolyPolygonInfo mLastPolyPolygonInfo
Definition: gdiimpl.hxx:345
virtual bool drawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt8 nTransparency)=0
SalInvert
Definition: salgtype.hxx:75
void setProvider(SalGeometryProvider *provider)
Definition: gdiimpl.hxx:252
virtual bool setClipRegion(const vcl::Region &)=0
static constexpr SkScalar toSkX(tools::Long x)
Definition: gdiimpl.hxx:297
SkBitmap mXorBitmap
Definition: gdiimpl.hxx:334
VCL_DLLPUBLIC void dump(const SkBitmap &bitmap, const char *file)
virtual bool drawPolyPolygonBezier(sal_uInt32 nPoly, const sal_uInt32 *pPoints, const Point *const *pPtAry, const PolyFlags *const *pFlgAry)=0
std::unique_ptr< sk_app::WindowContext > mWindowContext
Definition: gdiimpl.hxx:325
Reference< XOutputStream > stream
void addUpdateRegion(const SkRect &rect)
Definition: gdiimpl.hxx:272
SkCanvas * getDrawCanvas()
Definition: gdiimpl.hxx:234
virtual void Init()=0
virtual void invert(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, SalInvert nFlags)=0
virtual bool blendAlphaBitmap(const SalTwoRect &, const SalBitmap &rSrcBitmap, const SalBitmap &rMaskBitmap, const SalBitmap &rAlphaBitmap)=0
SkRegion mXorRegion
Definition: gdiimpl.hxx:336
static constexpr SkScalar toSkY(tools::Long y)
Definition: gdiimpl.hxx:298
unsigned char sal_uInt8
virtual OUString getRenderBackendName() const override
Definition: gdiimpl.hxx:50
virtual bool drawEPS(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, void *pPtr, sal_uInt32 nSize)=0
virtual void ResetClipRegion()=0
virtual void SetFillColor()=0
int GetHeight() const
Definition: gdiimpl.hxx:267
virtual void SetROPFillColor(SalROPColor nROPColor)=0
virtual void drawPixel(tools::Long nX, tools::Long nY)=0
virtual Color getPixel(tools::Long nX, tools::Long nY)=0
virtual std::shared_ptr< SalBitmap > getBitmap(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight)=0
virtual void drawMask(const SalTwoRect &rPosAry, const SalBitmap &rSalBitmap, Color nMaskColor)=0
virtual bool drawPolyLineBezier(sal_uInt32 nPoints, const Point *pPtAry, const PolyFlags *pFlgAry)=0
virtual void drawPolyLine(sal_uInt32 nPoints, const Point *pPtAry)=0
virtual void SetROPLineColor(SalROPColor nROPColor)=0
virtual sal_uInt16 GetBitCount() const =0
virtual bool drawTransformedBitmap(const basegfx::B2DPoint &rNull, const basegfx::B2DPoint &rX, const basegfx::B2DPoint &rY, const SalBitmap &rSourceBitmap, const SalBitmap *pAlphaBitmap, double fAlpha)=0
draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system ...
sk_sp< SkSurface > mSurface
Definition: gdiimpl.hxx:327
bool isGPU() const
Definition: gdiimpl.hxx:255
virtual bool drawPolygonBezier(sal_uInt32 nPoints, const Point *pPtAry, const PolyFlags *pFlgAry)=0
PolyFlags
::std::vector< B2DPolyPolygon > B2DPolyPolygonVector