1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <Qt5Graphics.hxx>
22 #include <Qt5Bitmap.hxx>
23 #include <Qt5Painter.hxx>
25 #include <sal/log.hxx>
27 #include <QtGui/QPainter>
28 #include <QtGui/QScreen>
29 #include <QtGui/QWindow>
30 #include <QtWidgets/QWidget>
33 #include <basegfx/polygon/b2dpolygontools.hxx>
34 #include <basegfx/polygon/b2dpolypolygontools.hxx>
36 const basegfx::B2DPoint
aHalfPointOfs(0.5, 0.5);
38 static void AddPolygonToPath(QPainterPath
& rPath
, const basegfx::B2DPolygon
& rPolygon
,
39 bool bClosePath
, bool bPixelSnap
, bool bLineDraw
)
41 const int nPointCount
= rPolygon
.count();
42 // short circuit if there is nothing to do
46 const bool bHasCurves
= rPolygon
.areControlPointsUsed();
47 for (int nPointIdx
= 0, nPrevIdx
= 0;; nPrevIdx
= nPointIdx
++)
49 int nClosedIdx
= nPointIdx
;
50 if (nPointIdx
>= nPointCount
)
52 // prepare to close last curve segment if needed
53 if (bClosePath
&& (nPointIdx
== nPointCount
))
59 basegfx::B2DPoint aPoint
= rPolygon
.getB2DPoint(nClosedIdx
);
63 // snap device coordinates to full pixels
64 aPoint
.setX(basegfx::fround(aPoint
.getX()));
65 aPoint
.setY(basegfx::fround(aPoint
.getY()));
69 aPoint
+= aHalfPointOfs
;
72 // first point => just move there
73 rPath
.moveTo(aPoint
.getX(), aPoint
.getY());
77 bool bPendingCurve
= false;
80 bPendingCurve
= rPolygon
.isNextControlPointUsed(nPrevIdx
);
81 bPendingCurve
|= rPolygon
.isPrevControlPointUsed(nClosedIdx
);
84 if (!bPendingCurve
) // line segment
85 rPath
.lineTo(aPoint
.getX(), aPoint
.getY());
86 else // cubic bezier segment
88 basegfx::B2DPoint aCP1
= rPolygon
.getNextControlPoint(nPrevIdx
);
89 basegfx::B2DPoint aCP2
= rPolygon
.getPrevControlPoint(nClosedIdx
);
92 aCP1
+= aHalfPointOfs
;
93 aCP2
+= aHalfPointOfs
;
95 rPath
.cubicTo(aCP1
.getX(), aCP1
.getY(), aCP2
.getX(), aCP2
.getY(), aPoint
.getX(),
101 rPath
.closeSubpath();
104 static bool AddPolyPolygonToPath(QPainterPath
& rPath
, const basegfx::B2DPolyPolygon
& rPolyPoly
,
105 bool bPixelSnap
, bool bLineDraw
)
107 if (rPolyPoly
.count() == 0)
109 for (auto const& rPolygon
: rPolyPoly
)
111 AddPolygonToPath(rPath
, rPolygon
, true, bPixelSnap
, bLineDraw
);
116 bool Qt5Graphics::setClipRegion(const vcl::Region
& rRegion
)
118 if (rRegion
.IsRectangle())
120 m_aClipRegion
= toQRect(rRegion
.GetBoundRect());
121 if (!m_aClipPath
.isEmpty())
124 m_aClipPath
.swap(aPath
);
127 else if (!rRegion
.HasPolyPolygonOrB2DPolyPolygon())
130 RectangleVector aRectangles
;
131 rRegion
.GetRegionRectangles(aRectangles
);
132 for (const auto& rRect
: aRectangles
)
133 aQRegion
+= toQRect(rRect
);
134 m_aClipRegion
= aQRegion
;
135 if (!m_aClipPath
.isEmpty())
138 m_aClipPath
.swap(aPath
);
144 const basegfx::B2DPolyPolygon
aPolyClip(rRegion
.GetAsB2DPolyPolygon());
145 AddPolyPolygonToPath(aPath
, aPolyClip
, !getAntiAlias(), false);
146 m_aClipPath
.swap(aPath
);
147 if (!m_aClipRegion
.isEmpty())
150 m_aClipRegion
.swap(aRegion
);
156 void Qt5Graphics::ResetClipRegion()
159 m_aClipRegion
= QRegion(m_pQImage
->rect());
161 m_aClipRegion
= QRegion();
162 if (!m_aClipPath
.isEmpty())
165 m_aClipPath
.swap(aPath
);
169 void Qt5Graphics::drawPixel(tools::Long nX
, tools::Long nY
)
171 Qt5Painter
aPainter(*this);
172 aPainter
.drawPoint(nX
, nY
);
173 aPainter
.update(nX
, nY
, 1, 1);
176 void Qt5Graphics::drawPixel(tools::Long nX
, tools::Long nY
, Color nColor
)
178 Qt5Painter
aPainter(*this);
179 aPainter
.setPen(toQColor(nColor
));
180 aPainter
.setPen(Qt::SolidLine
);
181 aPainter
.drawPoint(nX
, nY
);
182 aPainter
.update(nX
, nY
, 1, 1);
185 void Qt5Graphics::drawLine(tools::Long nX1
, tools::Long nY1
, tools::Long nX2
, tools::Long nY2
)
187 Qt5Painter
aPainter(*this);
188 aPainter
.drawLine(nX1
, nY1
, nX2
, nY2
);
203 aPainter
.update(nX1
, nY1
, nX2
- nX1
+ 1, nY2
- nY1
+ 1);
206 void Qt5Graphics::drawRect(tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
)
208 if (SALCOLOR_NONE
== m_aFillColor
&& SALCOLOR_NONE
== m_aLineColor
)
211 Qt5Painter
aPainter(*this, true);
212 if (SALCOLOR_NONE
!= m_aFillColor
)
213 aPainter
.fillRect(nX
, nY
, nWidth
, nHeight
, aPainter
.brush());
214 if (SALCOLOR_NONE
!= m_aLineColor
)
215 aPainter
.drawRect(nX
, nY
, nWidth
- 1, nHeight
- 1);
216 aPainter
.update(nX
, nY
, nWidth
, nHeight
);
219 void Qt5Graphics::drawPolyLine(sal_uInt32 nPoints
, const Point
* pPtAry
)
224 Qt5Painter
aPainter(*this);
225 QPoint
* pPoints
= new QPoint
[nPoints
];
226 QPoint
aTopLeft(pPtAry
->getX(), pPtAry
->getY());
227 QPoint aBottomRight
= aTopLeft
;
228 for (sal_uInt32 i
= 0; i
< nPoints
; ++i
, ++pPtAry
)
230 pPoints
[i
] = QPoint(pPtAry
->getX(), pPtAry
->getY());
231 if (pPtAry
->getX() < aTopLeft
.x())
232 aTopLeft
.setX(pPtAry
->getX());
233 if (pPtAry
->getY() < aTopLeft
.y())
234 aTopLeft
.setY(pPtAry
->getY());
235 if (pPtAry
->getX() > aBottomRight
.x())
236 aBottomRight
.setX(pPtAry
->getX());
237 if (pPtAry
->getY() > aBottomRight
.y())
238 aBottomRight
.setY(pPtAry
->getY());
240 aPainter
.drawPolyline(pPoints
, nPoints
);
242 aPainter
.update(QRect(aTopLeft
, aBottomRight
));
245 void Qt5Graphics::drawPolygon(sal_uInt32 nPoints
, const Point
* pPtAry
)
247 Qt5Painter
aPainter(*this, true);
248 QPolygon
aPolygon(nPoints
);
249 for (sal_uInt32 i
= 0; i
< nPoints
; ++i
, ++pPtAry
)
250 aPolygon
.setPoint(i
, pPtAry
->getX(), pPtAry
->getY());
251 aPainter
.drawPolygon(aPolygon
);
252 aPainter
.update(aPolygon
.boundingRect());
255 void Qt5Graphics::drawPolyPolygon(sal_uInt32 nPolyCount
, const sal_uInt32
* pPoints
,
256 const Point
** ppPtAry
)
258 // ignore invisible polygons
259 if (SALCOLOR_NONE
== m_aFillColor
&& SALCOLOR_NONE
== m_aLineColor
)
263 for (sal_uInt32 nPoly
= 0; nPoly
< nPolyCount
; nPoly
++)
265 const sal_uInt32 nPoints
= pPoints
[nPoly
];
268 const Point
* pPtAry
= ppPtAry
[nPoly
];
269 aPath
.moveTo(pPtAry
->getX(), pPtAry
->getY());
271 for (sal_uInt32 nPoint
= 1; nPoint
< nPoints
; nPoint
++, pPtAry
++)
272 aPath
.lineTo(pPtAry
->getX(), pPtAry
->getY());
273 aPath
.closeSubpath();
277 Qt5Painter
aPainter(*this, true);
278 aPainter
.drawPath(aPath
);
279 aPainter
.update(aPath
.boundingRect());
282 bool Qt5Graphics::drawPolyPolygon(const basegfx::B2DHomMatrix
& rObjectToDevice
,
283 const basegfx::B2DPolyPolygon
& rPolyPolygon
, double fTransparency
)
285 // ignore invisible polygons
286 if (SALCOLOR_NONE
== m_aFillColor
&& SALCOLOR_NONE
== m_aLineColor
)
288 if ((fTransparency
>= 1.0) || (fTransparency
< 0))
291 // Fallback: Transform to DeviceCoordinates
292 basegfx::B2DPolyPolygon
aPolyPolygon(rPolyPolygon
);
293 aPolyPolygon
.transform(rObjectToDevice
);
296 // ignore empty polygons
297 if (!AddPolyPolygonToPath(aPath
, aPolyPolygon
, !getAntiAlias(), m_aLineColor
!= SALCOLOR_NONE
))
300 Qt5Painter
aPainter(*this, true, 255 * (1.0 - fTransparency
));
301 aPainter
.drawPath(aPath
);
302 aPainter
.update(aPath
.boundingRect());
306 bool Qt5Graphics::drawPolyLineBezier(sal_uInt32
/*nPoints*/, const Point
* /*pPtAry*/,
307 const PolyFlags
* /*pFlgAry*/)
312 bool Qt5Graphics::drawPolygonBezier(sal_uInt32
/*nPoints*/, const Point
* /*pPtAry*/,
313 const PolyFlags
* /*pFlgAry*/)
318 bool Qt5Graphics::drawPolyPolygonBezier(sal_uInt32
/*nPoly*/, const sal_uInt32
* /*pPoints*/,
319 const Point
* const* /*pPtAry*/,
320 const PolyFlags
* const* /*pFlgAry*/)
325 bool Qt5Graphics::drawPolyLine(const basegfx::B2DHomMatrix
& rObjectToDevice
,
326 const basegfx::B2DPolygon
& rPolyLine
, double fTransparency
,
328 const std::vector
<double>* pStroke
, // MM01
329 basegfx::B2DLineJoin eLineJoin
, css::drawing::LineCap eLineCap
,
330 double fMiterMinimumAngle
, bool bPixelSnapHairline
)
332 if (SALCOLOR_NONE
== m_aFillColor
&& SALCOLOR_NONE
== m_aLineColor
)
337 // MM01 check done for simple reasons
338 if (!rPolyLine
.count() || fTransparency
< 0.0 || fTransparency
> 1.0)
343 // MM01 need to do line dashing as fallback stuff here now
344 const double fDotDashLength(
345 nullptr != pStroke
? std::accumulate(pStroke
->begin(), pStroke
->end(), 0.0) : 0.0);
346 const bool bStrokeUsed(0.0 != fDotDashLength
);
347 assert(!bStrokeUsed
|| (bStrokeUsed
&& pStroke
));
348 basegfx::B2DPolyPolygon aPolyPolygonLine
;
353 basegfx::utils::applyLineDashing(rPolyLine
, // source
355 &aPolyPolygonLine
, // target for lines
356 nullptr, // target for gaps
357 fDotDashLength
); // full length if available
361 // no line dashing, just copy
362 aPolyPolygonLine
.append(rPolyLine
);
365 // Transform to DeviceCoordinates, get DeviceLineWidth, execute PixelSnapHairline
366 aPolyPolygonLine
.transform(rObjectToDevice
);
367 if (bPixelSnapHairline
)
369 aPolyPolygonLine
= basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygonLine
);
372 // tdf#124848 get correct LineWidth in discrete coordinates,
373 if (fLineWidth
== 0) // hairline
375 else // Adjust line width for object-to-device scale.
376 fLineWidth
= (rObjectToDevice
* basegfx::B2DVector(fLineWidth
, 0)).getLength();
378 // setup poly-polygon path
381 // MM01 todo - I assume that this is OKAY to be done in one run for Qt5,
382 // but this NEEDS to be checked/verified
383 for (sal_uInt32
a(0); a
< aPolyPolygonLine
.count(); a
++)
385 const basegfx::B2DPolygon
aPolyLine(aPolyPolygonLine
.getB2DPolygon(a
));
386 AddPolygonToPath(aPath
, aPolyLine
, aPolyLine
.isClosed(), !getAntiAlias(), true);
389 Qt5Painter
aPainter(*this, false, 255 * (1.0 - fTransparency
));
391 // setup line attributes
392 QPen aPen
= aPainter
.pen();
393 aPen
.setWidth(fLineWidth
);
397 case basegfx::B2DLineJoin::Bevel
:
398 aPen
.setJoinStyle(Qt::BevelJoin
);
400 case basegfx::B2DLineJoin::Round
:
401 aPen
.setJoinStyle(Qt::RoundJoin
);
403 case basegfx::B2DLineJoin::NONE
:
404 case basegfx::B2DLineJoin::Miter
:
405 aPen
.setMiterLimit(1.0 / sin(fMiterMinimumAngle
/ 2.0));
406 aPen
.setJoinStyle(Qt::MiterJoin
);
412 default: // css::drawing::LineCap_BUTT:
413 aPen
.setCapStyle(Qt::FlatCap
);
415 case css::drawing::LineCap_ROUND
:
416 aPen
.setCapStyle(Qt::RoundCap
);
418 case css::drawing::LineCap_SQUARE
:
419 aPen
.setCapStyle(Qt::SquareCap
);
423 aPainter
.setPen(aPen
);
424 aPainter
.drawPath(aPath
);
425 aPainter
.update(aPath
.boundingRect());
429 bool Qt5Graphics::drawGradient(const tools::PolyPolygon
&, const Gradient
&) { return false; }
431 void Qt5Graphics::drawScaledImage(const SalTwoRect
& rPosAry
, const QImage
& rImage
)
433 Qt5Painter
aPainter(*this);
434 QRect
aSrcRect(rPosAry
.mnSrcX
, rPosAry
.mnSrcY
, rPosAry
.mnSrcWidth
, rPosAry
.mnSrcHeight
);
435 QRect
aDestRect(rPosAry
.mnDestX
, rPosAry
.mnDestY
, rPosAry
.mnDestWidth
, rPosAry
.mnDestHeight
);
436 aPainter
.drawImage(aDestRect
, rImage
, aSrcRect
);
437 aPainter
.update(aDestRect
);
440 void Qt5Graphics::copyArea(tools::Long nDestX
, tools::Long nDestY
, tools::Long nSrcX
,
441 tools::Long nSrcY
, tools::Long nSrcWidth
, tools::Long nSrcHeight
,
442 bool /*bWindowInvalidate*/)
444 if (nDestX
== nSrcX
&& nDestY
== nSrcY
)
447 SalTwoRect
aTR(nSrcX
, nSrcY
, nSrcWidth
, nSrcHeight
, nDestX
, nDestY
, nSrcWidth
, nSrcHeight
);
451 void Qt5Graphics::copyBits(const SalTwoRect
& rPosAry
, SalGraphics
* pSrcGraphics
)
453 if (rPosAry
.mnSrcWidth
<= 0 || rPosAry
.mnSrcHeight
<= 0 || rPosAry
.mnDestWidth
<= 0
454 || rPosAry
.mnDestHeight
<= 0)
457 QImage aImage
, *pImage
;
458 SalTwoRect aPosAry
= rPosAry
;
459 if (!pSrcGraphics
|| this == pSrcGraphics
)
463 = pImage
->copy(rPosAry
.mnSrcX
, rPosAry
.mnSrcY
, rPosAry
.mnSrcWidth
, rPosAry
.mnSrcHeight
);
469 pImage
= static_cast<Qt5Graphics
*>(pSrcGraphics
)->m_pQImage
;
471 drawScaledImage(aPosAry
, *pImage
);
474 void Qt5Graphics::drawBitmap(const SalTwoRect
& rPosAry
, const SalBitmap
& rSalBitmap
)
476 if (rPosAry
.mnSrcWidth
<= 0 || rPosAry
.mnSrcHeight
<= 0 || rPosAry
.mnDestWidth
<= 0
477 || rPosAry
.mnDestHeight
<= 0)
480 Qt5Bitmap aRGBABitmap
;
481 if (rSalBitmap
.GetBitCount() == 4)
482 aRGBABitmap
.Create(rSalBitmap
, 32);
483 const QImage
* pImage
= (rSalBitmap
.GetBitCount() != 4)
484 ? static_cast<const Qt5Bitmap
*>(&rSalBitmap
)->GetQImage()
485 : aRGBABitmap
.GetQImage();
488 drawScaledImage(rPosAry
, *pImage
);
491 void Qt5Graphics::drawBitmap(const SalTwoRect
& rPosAry
, const SalBitmap
& /*rSalBitmap*/,
492 const SalBitmap
& /*rTransparentBitmap*/)
494 if (rPosAry
.mnSrcWidth
<= 0 || rPosAry
.mnSrcHeight
<= 0 || rPosAry
.mnDestWidth
<= 0
495 || rPosAry
.mnDestHeight
<= 0)
498 assert(rPosAry
.mnSrcWidth
== rPosAry
.mnDestWidth
);
499 assert(rPosAry
.mnSrcHeight
== rPosAry
.mnDestHeight
);
502 void Qt5Graphics::drawMask(const SalTwoRect
& rPosAry
, const SalBitmap
& /*rSalBitmap*/,
503 Color
/*nMaskColor*/)
505 if (rPosAry
.mnSrcWidth
<= 0 || rPosAry
.mnSrcHeight
<= 0 || rPosAry
.mnDestWidth
<= 0
506 || rPosAry
.mnDestHeight
<= 0)
509 assert(rPosAry
.mnSrcWidth
== rPosAry
.mnDestWidth
);
510 assert(rPosAry
.mnSrcHeight
== rPosAry
.mnDestHeight
);
513 std::shared_ptr
<SalBitmap
> Qt5Graphics::getBitmap(tools::Long nX
, tools::Long nY
,
514 tools::Long nWidth
, tools::Long nHeight
)
516 return std::make_shared
<Qt5Bitmap
>(m_pQImage
->copy(nX
, nY
, nWidth
, nHeight
));
519 Color
Qt5Graphics::getPixel(tools::Long nX
, tools::Long nY
) { return m_pQImage
->pixel(nX
, nY
); }
521 void Qt5Graphics::invert(tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
,
524 Qt5Painter
aPainter(*this);
525 if (SalInvert::N50
& nFlags
)
527 aPainter
.setCompositionMode(QPainter::RasterOp_SourceXorDestination
);
528 QBrush
aBrush(Qt::white
, Qt::Dense4Pattern
);
529 aPainter
.fillRect(nX
, nY
, nWidth
, nHeight
, aBrush
);
533 if (SalInvert::TrackFrame
& nFlags
)
535 aPainter
.setCompositionMode(QPainter::RasterOp_SourceXorDestination
);
536 QPen
aPen(Qt::white
);
537 aPen
.setStyle(Qt::DotLine
);
538 aPainter
.setPen(aPen
);
539 aPainter
.drawRect(nX
, nY
, nWidth
, nHeight
);
543 aPainter
.setCompositionMode(QPainter::RasterOp_SourceXorDestination
);
544 aPainter
.fillRect(nX
, nY
, nWidth
, nHeight
, Qt::white
);
547 aPainter
.update(nX
, nY
, nWidth
, nHeight
);
550 void Qt5Graphics::invert(sal_uInt32
/*nPoints*/, const Point
* /*pPtAry*/, SalInvert
/*nFlags*/) {}
552 bool Qt5Graphics::drawEPS(tools::Long
/*nX*/, tools::Long
/*nY*/, tools::Long
/*nWidth*/,
553 tools::Long
/*nHeight*/, void* /*pPtr*/, sal_uInt32
/*nSize*/)
558 bool Qt5Graphics::blendBitmap(const SalTwoRect
&, const SalBitmap
& /*rBitmap*/) { return false; }
560 bool Qt5Graphics::blendAlphaBitmap(const SalTwoRect
&, const SalBitmap
& /*rSrcBitmap*/,
561 const SalBitmap
& /*rMaskBitmap*/,
562 const SalBitmap
& /*rAlphaBitmap*/)
567 static bool getAlphaImage(const SalBitmap
& rSourceBitmap
, const SalBitmap
& rAlphaBitmap
,
570 if (rAlphaBitmap
.GetBitCount() != 8 && rAlphaBitmap
.GetBitCount() != 1)
572 SAL_WARN("vcl.gdi", "unsupported alpha depth case: " << rAlphaBitmap
.GetBitCount());
576 Qt5Bitmap aRGBABitmap
;
577 if (rSourceBitmap
.GetBitCount() == 4)
578 aRGBABitmap
.Create(rSourceBitmap
, 32);
579 const QImage
* pBitmap
= (rSourceBitmap
.GetBitCount() != 4)
580 ? static_cast<const Qt5Bitmap
*>(&rSourceBitmap
)->GetQImage()
581 : aRGBABitmap
.GetQImage();
582 const QImage
* pAlpha
= static_cast<const Qt5Bitmap
*>(&rAlphaBitmap
)->GetQImage();
583 rAlphaImage
= pBitmap
->convertToFormat(Qt5_DefaultFormat32
);
585 if (rAlphaBitmap
.GetBitCount() == 8)
587 for (int y
= 0; y
< rAlphaImage
.height(); ++y
)
589 uchar
* image_line
= rAlphaImage
.scanLine(y
);
590 const uchar
* alpha_line
= pAlpha
->scanLine(y
);
591 for (int x
= 0; x
< rAlphaImage
.width(); ++x
, image_line
+= 4)
592 image_line
[3] = 255 - alpha_line
[x
];
597 for (int y
= 0; y
< rAlphaImage
.height(); ++y
)
599 uchar
* image_line
= rAlphaImage
.scanLine(y
);
600 const uchar
* alpha_line
= pAlpha
->scanLine(y
);
601 for (int x
= 0; x
< rAlphaImage
.width(); ++x
, image_line
+= 4)
605 if (0 != (*alpha_line
& (1 << (7 - x
% 8))))
614 bool Qt5Graphics::drawAlphaBitmap(const SalTwoRect
& rPosAry
, const SalBitmap
& rSourceBitmap
,
615 const SalBitmap
& rAlphaBitmap
)
618 if (!getAlphaImage(rSourceBitmap
, rAlphaBitmap
, aImage
))
620 drawScaledImage(rPosAry
, aImage
);
624 bool Qt5Graphics::drawTransformedBitmap(const basegfx::B2DPoint
& rNull
, const basegfx::B2DPoint
& rX
,
625 const basegfx::B2DPoint
& rY
, const SalBitmap
& rSourceBitmap
,
626 const SalBitmap
* pAlphaBitmap
)
629 if (pAlphaBitmap
&& !getAlphaImage(rSourceBitmap
, *pAlphaBitmap
, aImage
))
633 Qt5Bitmap aRGBABitmap
;
634 if (rSourceBitmap
.GetBitCount() == 4)
635 aRGBABitmap
.Create(rSourceBitmap
, 32);
636 const QImage
* pBitmap
= (rSourceBitmap
.GetBitCount() != 4)
637 ? static_cast<const Qt5Bitmap
*>(&rSourceBitmap
)->GetQImage()
638 : aRGBABitmap
.GetQImage();
639 aImage
= pBitmap
->convertToFormat(Qt5_DefaultFormat32
);
642 Qt5Painter
aPainter(*this);
643 const basegfx::B2DVector aXRel
= rX
- rNull
;
644 const basegfx::B2DVector aYRel
= rY
- rNull
;
645 aPainter
.setTransform(QTransform(aXRel
.getX() / aImage
.width(), aXRel
.getY() / aImage
.width(),
646 aYRel
.getX() / aImage
.height(), aYRel
.getY() / aImage
.height(),
647 rNull
.getX(), rNull
.getY()));
648 aPainter
.drawImage(QPoint(0, 0), aImage
);
649 aPainter
.update(aImage
.rect());
653 bool Qt5Graphics::drawAlphaRect(tools::Long nX
, tools::Long nY
, tools::Long nWidth
,
654 tools::Long nHeight
, sal_uInt8 nTransparency
)
656 if (SALCOLOR_NONE
== m_aFillColor
&& SALCOLOR_NONE
== m_aLineColor
)
658 assert(nTransparency
<= 100);
659 if (nTransparency
> 100)
661 Qt5Painter
aPainter(*this, true, (100 - nTransparency
) * (255.0 / 100));
662 if (SALCOLOR_NONE
!= m_aFillColor
)
663 aPainter
.fillRect(nX
, nY
, nWidth
, nHeight
, aPainter
.brush());
664 if (SALCOLOR_NONE
!= m_aLineColor
)
665 aPainter
.drawRect(nX
, nY
, nWidth
- 1, nHeight
- 1);
666 aPainter
.update(nX
, nY
, nWidth
, nHeight
);
670 void Qt5Graphics::GetResolution(sal_Int32
& rDPIX
, sal_Int32
& rDPIY
)
673 if ((pForceDpi
= getenv("SAL_FORCEDPI")))
675 OString
sForceDPI(pForceDpi
);
676 rDPIX
= rDPIY
= sForceDPI
.toInt32();
680 if (!m_pFrame
|| !m_pFrame
->GetQWidget()->window()->windowHandle())
683 QScreen
* pScreen
= m_pFrame
->GetQWidget()->window()->windowHandle()->screen();
684 rDPIX
= pScreen
->logicalDotsPerInchX() * pScreen
->devicePixelRatio() + 0.5;
685 rDPIY
= pScreen
->logicalDotsPerInchY() * pScreen
->devicePixelRatio() + 0.5;
688 sal_uInt16
Qt5Graphics::GetBitCount() const { return getFormatBits(m_pQImage
->format()); }
690 tools::Long
Qt5Graphics::GetGraphicsWidth() const { return m_pQImage
->width(); }
692 void Qt5Graphics::SetLineColor() { m_aLineColor
= SALCOLOR_NONE
; }
694 void Qt5Graphics::SetLineColor(Color nColor
) { m_aLineColor
= nColor
; }
696 void Qt5Graphics::SetFillColor() { m_aFillColor
= SALCOLOR_NONE
; }
698 void Qt5Graphics::SetFillColor(Color nColor
) { m_aFillColor
= nColor
; }
700 void Qt5Graphics::SetXORMode(bool bSet
, bool)
703 m_eCompositionMode
= QPainter::CompositionMode_Xor
;
705 m_eCompositionMode
= QPainter::CompositionMode_SourceOver
;
708 void Qt5Graphics::SetROPLineColor(SalROPColor
/*nROPColor*/) {}
710 void Qt5Graphics::SetROPFillColor(SalROPColor
/*nROPColor*/) {}
712 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */