LibreOffice Module vcl (master)  1
skia/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 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(long nX, long nY) override;
90  virtual void drawPixel(long nX, long nY, Color nColor) override;
91 
92  virtual void drawLine(long nX1, long nY1, long nX2, long nY2) override;
93 
94  virtual void drawRect(long nX, long nY, long nWidth, long nHeight) override;
95 
96  virtual void drawPolyLine(sal_uInt32 nPoints, const SalPoint* pPtAry) override;
97 
98  virtual void drawPolygon(sal_uInt32 nPoints, const SalPoint* pPtAry) override;
99 
100  virtual void drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32* pPoints,
101  PCONSTSALPOINT* pPtAry) override;
102 
103  virtual bool drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectToDevice,
104  const basegfx::B2DPolyPolygon&, double fTransparency) override;
105 
106  virtual bool drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice,
107  const basegfx::B2DPolygon&, double fTransparency, double fLineWidth,
108  const std::vector<double>* pStroke, basegfx::B2DLineJoin,
109  css::drawing::LineCap, double fMiterMinimumAngle,
110  bool bPixelSnapHairline) override;
111 
112  virtual bool drawPolyLineBezier(sal_uInt32 nPoints, const SalPoint* pPtAry,
113  const PolyFlags* pFlgAry) override;
114 
115  virtual bool drawPolygonBezier(sal_uInt32 nPoints, const SalPoint* pPtAry,
116  const PolyFlags* pFlgAry) override;
117 
118  virtual bool drawPolyPolygonBezier(sal_uInt32 nPoly, const sal_uInt32* pPoints,
119  const SalPoint* const* pPtAry,
120  const PolyFlags* const* pFlgAry) override;
121 
122  // CopyArea --> No RasterOp, but ClipRegion
123  virtual void copyArea(long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth,
124  long nSrcHeight, bool bWindowInvalidate) override;
125 
126  virtual void copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics) override;
127 
128  virtual bool blendBitmap(const SalTwoRect&, const SalBitmap& rBitmap) override;
129 
130  virtual bool blendAlphaBitmap(const SalTwoRect&, const SalBitmap& rSrcBitmap,
131  const SalBitmap& rMaskBitmap,
132  const SalBitmap& rAlphaBitmap) override;
133 
134  virtual void drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap) override;
135 
136  virtual void drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap,
137  const SalBitmap& rMaskBitmap) override;
138 
139  virtual void drawMask(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap,
140  Color nMaskColor) override;
141 
142  virtual std::shared_ptr<SalBitmap> getBitmap(long nX, long nY, long nWidth,
143  long nHeight) override;
144 
145  virtual Color getPixel(long nX, long nY) override;
146 
147  // invert --> ClipRegion (only Windows or VirDevs)
148  virtual void invert(long nX, long nY, long nWidth, long nHeight, SalInvert nFlags) override;
149 
150  virtual void invert(sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags) override;
151 
152  virtual bool drawEPS(long nX, long nY, long nWidth, long nHeight, void* pPtr,
153  sal_uInt32 nSize) override;
154 
167  virtual bool drawAlphaBitmap(const SalTwoRect&, const SalBitmap& rSourceBitmap,
168  const SalBitmap& rAlphaBitmap) override;
169 
171  virtual bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
172  const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
173  const SalBitmap* pAlphaBitmap) override;
174 
190  virtual bool drawAlphaRect(long nX, long nY, long nWidth, long nHeight,
191  sal_uInt8 nTransparency) override;
192 
193  virtual bool drawGradient(const tools::PolyPolygon& rPolygon,
194  const Gradient& rGradient) override;
195 
196  virtual bool supportsOperation(OutDevSupportType eType) const override;
197 
198 #ifdef DBG_UTIL
199  void dump(const char* file) const;
200 #endif
201 
202  // Default blend mode for SkPaint is SkBlendMode::kSrcOver
203  void drawBitmap(const SalTwoRect& rPosAry, const SkiaSalBitmap& bitmap,
204  SkBlendMode blendMode = SkBlendMode::kSrcOver);
205 
206  void drawImage(const SalTwoRect& rPosAry, const sk_sp<SkImage>& aImage,
207  SkBlendMode eBlendMode = SkBlendMode::kSrcOver);
208 
209  void drawShader(const SalTwoRect& rPosAry, const sk_sp<SkShader>& shader,
210  SkBlendMode blendMode = SkBlendMode::kSrcOver);
211 
212  enum class GlyphOrientation
213  {
214  Apply,
215  Ignore
216  };
217  void drawGenericLayout(const GenericSalLayout& layout, Color textColor, const SkFont& font,
218  GlyphOrientation glyphOrientation);
219 
220 protected:
221  // To be called before any drawing.
222  void preDraw();
223  // To be called after any drawing.
224  void postDraw();
225  // The canvas to draw to. Will be diverted to a temporary for Xor mode.
226  SkCanvas* getDrawCanvas() { return mXorMode ? getXorCanvas() : mSurface->getCanvas(); }
227  // Call before makeImageSnapshot(), ensures the content is up to date.
228  void flushDrawing();
229 
230  virtual void createSurface();
231  // Call to ensure that mSurface is valid. If mSurface is going to be modified,
232  // use preDraw() instead of this.
233  void checkSurface();
234  void recreateSurface();
235  void destroySurface();
236  // Reimplemented for X11.
237  virtual bool avoidRecreateByResize() const { return false; }
238  void createWindowSurface();
239  virtual void createWindowContext() = 0;
240  void createOffscreenSurface();
241 
242  void privateDrawAlphaRect(long nX, long nY, long nWidth, long nHeight, double nTransparency,
243  bool blockAA = false);
244 
245  void setProvider(SalGeometryProvider* provider) { mProvider = provider; }
246 
247  bool isOffscreen() const { return mProvider == nullptr || mProvider->IsOffScreen(); }
248  bool isGPU() const { return mIsGPU; }
249 
250  void invert(basegfx::B2DPolygon const& rPoly, SalInvert eFlags);
251 
252  // Called by SkiaFlushIdle.
253  virtual void performFlush() = 0;
254  void scheduleFlush();
255  friend class SkiaFlushIdle;
256 
257  // get the width of the device
258  int GetWidth() const { return mProvider ? mProvider->GetWidth() : 1; }
259  // get the height of the device
260  int GetHeight() const { return mProvider ? mProvider->GetHeight() : 1; }
261 
262  SkCanvas* getXorCanvas();
263  void applyXor();
264  void addXorRegion(const SkRect& rect)
265  {
266  if (mXorMode)
267  {
268  // Make slightly larger, just in case (rounding, antialiasing,...).
269  mXorRegion.op(rect.makeOutset(2, 2).round(), SkRegion::kUnion_Op);
270  }
271  }
272  static void setCanvasClipRegion(SkCanvas* canvas, const vcl::Region& region);
273  sk_sp<SkImage> mergeCacheBitmaps(const SkiaSalBitmap& bitmap, const SkiaSalBitmap* alphaBitmap,
274  const Size targetSize);
275 
276  // Skia uses floating point coordinates, so when we use integer coordinates, sometimes
277  // rounding results in off-by-one errors (down), especially when drawing using GPU,
278  // see https://bugs.chromium.org/p/skia/issues/detail?id=9611 . Compensate for
279  // it by using centers of pixels. Using 0.5 may sometimes round up, so go with 0.495 .
280  static constexpr SkScalar toSkX(long x) { return x + 0.495; }
281  static constexpr SkScalar toSkY(long y) { return y + 0.495; }
282  // Value to add to be exactly in the middle of the pixel.
283  static constexpr SkScalar toSkXYFix = SkScalar(0.005);
284 
285  // Perform any pending drawing such as delayed merging of polygons. Called by preDraw()
286  // and anything that means the next operation cannot be another one in a series (e.g.
287  // changing colors).
288  void checkPendingDrawing();
289  bool mergePolyPolygonToPrevious(const basegfx::B2DPolyPolygon& polygon, double transparency);
290  void performDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double transparency,
291  bool useAA);
292 
293  template <typename charT, typename traits>
294  friend inline std::basic_ostream<charT, traits>&
295  operator<<(std::basic_ostream<charT, traits>& stream, const SkiaSalGraphicsImpl* graphics)
296  {
297  if (graphics == nullptr)
298  return stream << "(null)";
299  // O - offscreen, G - GPU-based, R - raster
300  return stream << static_cast<const void*>(graphics) << " "
301  << Size(graphics->GetWidth(), graphics->GetHeight())
302  << (graphics->isGPU() ? "G" : "R") << (graphics->isOffscreen() ? "O" : "");
303  }
304 
308  std::unique_ptr<sk_app::WindowContext> mWindowContext;
309  // The Skia surface that is target of all the rendering.
310  sk_sp<SkSurface> mSurface;
311  bool mIsGPU; // whether the surface is GPU-backed
312  // Keep reference to shared GrContext.
316  bool mXorMode;
317  SkBitmap mXorBitmap;
318  std::unique_ptr<SkCanvas> mXorCanvas;
319  SkRegion mXorRegion; // the area that needs updating for the xor operation
320  std::unique_ptr<SkiaFlushIdle> mFlush;
321  // Info about pending polygons to draw (we try to merge adjacent polygons into one).
323  {
325  double transparency;
326  };
328 };
329 
330 #endif
331 
332 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Interface used to share logic on sizing between SalVirtualDevices and SalFrames.
Definition: salgeom.hxx:62
vcl::Region mClipRegion
virtual std::shared_ptr< SalBitmap > getBitmap(long nX, long nY, long nWidth, long nHeight)=0
virtual void drawRect(long nX, long nY, long nWidth, long nHeight)=0
SalGeometryProvider * mProvider
Pointer to the SalFrame or SalVirtualDevice.
virtual void drawBitmap(const SalTwoRect &rPosAry, const SalBitmap &rSalBitmap)=0
SalROPColor
Definition: salgtype.hxx:80
virtual bool drawAlphaBitmap(const SalTwoRect &, const SalBitmap &rSourceBitmap, const SalBitmap &rAlphaBitmap)=0
virtual Color getPixel(long nX, long nY)=0
virtual void copyBits(const SalTwoRect &rPosAry, SalGraphics *pSrcGraphics)=0
int GetWidth() const
virtual void SetXORMode(bool bSet, bool bInvertOnly)=0
#define VCL_DLLPUBLIC
Definition: dllapi.h:29
virtual void copyArea(long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth, long nSrcHeight, bool bWindowInvalidate)=0
virtual void drawPolyLine(sal_uInt32 nPoints, const SalPoint *pPtAry)=0
virtual bool supportsOperation(OutDevSupportType eType) const =0
std::unique_ptr< SkiaFlushIdle > mFlush
OutDevSupportType
Definition: vclenum.hxx:198
bool isOffscreen() const
SalGraphics & mParent
virtual void drawPixel(long nX, long nY)=0
virtual bool drawGradient(const tools::PolyPolygon &rPolygon, const Gradient &rGradient)=0
virtual bool blendBitmap(const SalTwoRect &, const SalBitmap &rBitmap)=0
virtual void invert(long nX, long nY, long nWidth, long nHeight, SalInvert nFlags)=0
virtual long GetGraphicsWidth() const =0
static constexpr SkScalar toSkX(long x)
std::unique_ptr< SkCanvas > mXorCanvas
virtual void SetLineColor()=0
static constexpr SkScalar toSkY(long y)
virtual bool drawAlphaRect(long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency)=0
virtual void drawPolygon(sal_uInt32 nPoints, const SalPoint *pPtAry)=0
virtual bool drawPolyPolygonBezier(sal_uInt32 nPoly, const sal_uInt32 *pPoints, const SalPoint *const *pPtAry, const PolyFlags *const *pFlgAry)=0
virtual void DeInit()
Definition: salgdiimpl.hxx:49
virtual bool drawTransformedBitmap(const basegfx::B2DPoint &rNull, const basegfx::B2DPoint &rX, const basegfx::B2DPoint &rY, const SalBitmap &rSourceBitmap, const SalBitmap *pAlphaBitmap)=0
draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system ...
LastPolyPolygonInfo mLastPolyPolygonInfo
virtual void drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32 *pPoints, PCONSTSALPOINT *pPtAry)=0
virtual bool avoidRecreateByResize() const
SalInvert
Definition: salgtype.hxx:84
void setProvider(SalGeometryProvider *provider)
virtual void drawLine(long nX1, long nY1, long nX2, long nY2)=0
virtual bool setClipRegion(const vcl::Region &)=0
VCL_DLLPUBLIC void dump(const SkBitmap &bitmap, const char *file)
std::unique_ptr< sk_app::WindowContext > mWindowContext
Reference< XOutputStream > stream
virtual bool drawPolygonBezier(sal_uInt32 nPoints, const SalPoint *pPtAry, const PolyFlags *pFlgAry)=0
SkCanvas * getDrawCanvas()
virtual void Init()=0
virtual bool blendAlphaBitmap(const SalTwoRect &, const SalBitmap &rSrcBitmap, const SalBitmap &rMaskBitmap, const SalBitmap &rAlphaBitmap)=0
unsigned char sal_uInt8
virtual OUString getRenderBackendName() const override
virtual void ResetClipRegion()=0
virtual void SetFillColor()=0
int GetHeight() const
void addXorRegion(const SkRect &rect)
virtual void SetROPFillColor(SalROPColor nROPColor)=0
virtual bool drawEPS(long nX, long nY, long nWidth, long nHeight, void *pPtr, sal_uInt32 nSize)=0
virtual bool drawPolyLineBezier(sal_uInt32 nPoints, const SalPoint *pPtAry, const PolyFlags *pFlgAry)=0
virtual void drawMask(const SalTwoRect &rPosAry, const SalBitmap &rSalBitmap, Color nMaskColor)=0
virtual void SetROPLineColor(SalROPColor nROPColor)=0
virtual sal_uInt16 GetBitCount() const =0
sk_sp< SkSurface > mSurface
bool isGPU() const
PolyFlags