[Libreoffice-commits] core.git: vcl/inc vcl/ios vcl/Library_vclplug_osx.mk vcl/osx vcl/quartz
Tomaž Vajngerl (via logerrit)
logerrit at kemper.freedesktop.org
Fri Apr 30 10:21:08 UTC 2021
vcl/Library_vclplug_osx.mk | 1
vcl/inc/quartz/salgdi.h | 445 +++++++----
vcl/ios/dummies.cxx | 5
vcl/ios/salios.cxx | 142 ++-
vcl/osx/salgdiutils.cxx | 101 +-
vcl/osx/salmacos.cxx | 130 +--
vcl/osx/salnativewidgets.cxx | 88 +-
vcl/quartz/AquaGraphicsBackend.cxx | 1355 ++++++++++++++++++++++++++++++++++++
vcl/quartz/salgdi.cxx | 106 --
vcl/quartz/salgdicommon.cxx | 1392 +------------------------------------
10 files changed, 1953 insertions(+), 1812 deletions(-)
New commits:
commit 560c9ec9e27e771d61f1396a1c87dd38e29099c1
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Wed Apr 7 23:36:57 2021 +0900
Commit: Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Fri Apr 30 12:20:27 2021 +0200
vcl: iOS/macOS - move graphic render func. into AquaGraphicsBackend
This change moves graphic rendering function under AquaSalGraphics
into a new AquaGraphicsBackend, which inherits from SalGraphicsImpl.
This is part of the refactoring to make it mandatory that a
SalGraphics always has a SalGraphicsImpl associated, which will
make it possible to simplify the SalGraphics interface and enable
the posibility to implement alernative graphic backends (Skia).
Common variables and attributes are moved to AquaSharedAttributes
and are shared between SalGraphics and SalGraphicsImpl.
Change-Id: Ie48da87002ec8e4011ba92fdc9170f3a86761517
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114701
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
diff --git a/vcl/Library_vclplug_osx.mk b/vcl/Library_vclplug_osx.mk
index c80d3bc8d7f3..4b2b4a61b3f4 100644
--- a/vcl/Library_vclplug_osx.mk
+++ b/vcl/Library_vclplug_osx.mk
@@ -137,6 +137,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_osx,\
vcl/quartz/salgdicommon \
vcl/quartz/salvd \
vcl/quartz/utils \
+ vcl/quartz/AquaGraphicsBackend \
))
$(eval $(call gb_Library_use_system_darwin_frameworks,vclplug_osx,\
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index 80e6c66d1a00..e7559c5b9e7d 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -130,177 +130,326 @@ private:
std::unordered_map<sal_IntPtr, rtl::Reference<CoreTextFontFace>> maFontContainer;
};
-class AquaSalGraphics : public SalGraphics
+namespace sal::aqua
{
+float getWindowScaling();
+}
+
+struct AquaSharedAttributes
+{
+ /// path representing current clip region
+ CGMutablePathRef mxClipPath;
+
+ /// Drawing colors
+ /// pen color RGBA
+ RGBAColor maLineColor;
+
+ /// brush color RGBA
+ RGBAColor maFillColor;
+
+ // Graphics types
+#ifdef MACOSX
+ AquaSalFrame* mpFrame;
+ /// is this a window graphics
+ bool mbWindow;
+#else // IOS
+ // mirror AquaSalVirtualDevice::mbForeignContext for SvpSalGraphics objects related to such
+ bool mbForeignContext;
+#endif
+ /// is this a printer graphics
+ bool mbPrinter;
+ /// is this a virtual device graphics
+ bool mbVirDev;
+
CGLayerHolder maLayer; // Quartz graphics layer
CGContextHolder maContextHolder; // Quartz drawing context
CGContextHolder maBGContextHolder; // Quartz drawing context for CGLayer
CGContextHolder maCSContextHolder; // Quartz drawing context considering the color space
+ int mnWidth;
+ int mnHeight;
+ int mnXorMode; // 0: off 1: on 2: invert only
+ int mnBitmapDepth; // zero unless bitmap
std::unique_ptr<XorEmulation> mpXorEmulation;
- int mnXorMode; // 0: off 1: on 2: invert only
- int mnWidth;
- int mnHeight;
- int mnBitmapDepth; // zero unless bitmap
- /// device resolution of this graphics
- sal_Int32 mnRealDPIX;
- sal_Int32 mnRealDPIY;
- /// path representing current clip region
- CGMutablePathRef mxClipPath;
+ AquaSharedAttributes()
+ : mxClipPath(nullptr)
+ , maLineColor(COL_WHITE)
+ , maFillColor(COL_BLACK)
+#ifdef MACOSX
+ , mpFrame(nullptr)
+ , mbWindow(false)
+#else
+ , mbForeignContext(false)
+#endif
+ , mbPrinter(false)
+ , mbVirDev(false)
+ , mnWidth(0)
+ , mnHeight(0)
+ , mnXorMode(0)
+ , mnBitmapDepth(0)
+ {}
+
+ void unsetClipPath()
+ {
+ if (mxClipPath)
+ {
+ CGPathRelease(mxClipPath);
+ mxClipPath = nullptr;
+ }
+ }
+
+ void unsetState()
+ {
+ unsetClipPath();
+ }
+
+ bool checkContext();
+ void setState();
+
+ bool isPenVisible() const
+ {
+ return maLineColor.IsVisible();
+ }
+ bool isBrushVisible() const
+ {
+ return maFillColor.IsVisible();
+ }
+
+ void refreshRect(float lX, float lY, float lWidth, float lHeight)
+ {
+#ifdef MACOSX
+ if (!mbWindow) // view only on Window graphics
+ return;
+
+ if (mpFrame)
+ {
+ // update a little more around the designated rectangle
+ // this helps with antialiased rendering
+ // Rounding down x and width can accumulate a rounding error of up to 2
+ // The decrementing of x, the rounding error and the antialiasing border
+ // require that the width and the height need to be increased by four
+ const tools::Rectangle aVclRect(
+ Point(tools::Long(lX - 1), tools::Long(lY - 1)),
+ Size(tools::Long(lWidth + 4), tools::Long(lHeight + 4)));
+
+ mpFrame->maInvalidRect.Union(aVclRect);
+ }
+#else
+ (void) lX;
+ (void) lY;
+ (void) lWidth;
+ (void) lHeight;
+ return;
+#endif
+ }
+
+ // apply the XOR mask to the target context if active and dirty
+ void applyXorContext()
+ {
+ if (!mpXorEmulation)
+ return;
+ if (mpXorEmulation->UpdateTarget())
+ {
+ refreshRect(0, 0, mnWidth, mnHeight); // TODO: refresh minimal changerect
+ }
+ }
- /// Drawing colors
- /// pen color RGBA
- RGBAColor maLineColor;
- /// brush color RGBA
- RGBAColor maFillColor;
+ // differences between VCL, Quartz and kHiThemeOrientation coordinate systems
+ // make some graphics seem to be vertically-mirrored from a VCL perspective
+ bool isFlipped() const
+ {
+ #ifdef MACOSX
+ return mbWindow;
+ #else
+ return false;
+ #endif
+ }
+};
- // Device Font settings
- rtl::Reference<CoreTextStyle> mpTextStyle[MAX_FALLBACK];
- RGBAColor maTextColor;
- /// allows text to be rendered without antialiasing
- bool mbNonAntialiasedText;
+class AquaGraphicsBackend final : public SalGraphicsImpl
+{
+private:
+ AquaSharedAttributes& mrShared;
+
+ void drawPixelImpl( tools::Long nX, tools::Long nY, const RGBAColor& rColor); // helper to draw single pixels
#ifdef MACOSX
- AquaSalFrame* mpFrame;
+ void refreshRect(const NSRect& rRect)
+ {
+ mrShared.refreshRect(rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height);
+ }
+#else
+ void refreshRect(const CGRect& /*rRect*/)
+ {}
#endif
- // Graphics types
+ void pattern50Fill();
- /// is this a printer graphics
- bool mbPrinter;
- /// is this a virtual device graphics
- bool mbVirDev;
#ifdef MACOSX
- /// is this a window graphics
- bool mbWindow;
+protected:
+ void copyScaledArea(tools::Long nDestX, tools::Long nDestY, tools::Long nSrcX, tools::Long nSrcY,
+ tools::Long nSrcWidth, tools::Long nSrcHeight, AquaSharedAttributes* pSrcShared);
+#endif
-#else // IOS
+public:
+ AquaGraphicsBackend(AquaSharedAttributes & rShared);
+ ~AquaGraphicsBackend() override;
- // mirror AquaSalVirtualDevice::mbForeignContext for SvpSalGraphics objects related to such
- bool mbForeignContext;
+ void Init() override;
-#endif
+ void freeResources() override;
+
+ OUString getRenderBackendName() const override
+ {
+ return "aqua";
+ }
+
+ bool setClipRegion(vcl::Region const& rRegion) override;
+ void ResetClipRegion() override;
+
+ sal_uInt16 GetBitCount() const override;
+
+ tools::Long GetGraphicsWidth() const override;
+
+ void SetLineColor() override;
+ void SetLineColor(Color nColor) override;
+ void SetFillColor() override;
+ void SetFillColor(Color nColor) override;
+ void SetXORMode(bool bSet, bool bInvertOnly) override;
+ void SetROPLineColor(SalROPColor nROPColor) override;
+ void SetROPFillColor(SalROPColor nROPColor) override;
+
+ void drawPixel(tools::Long nX, tools::Long nY) override;
+ void drawPixel(tools::Long nX, tools::Long nY, Color nColor) override;
+
+ void drawLine(tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2) override;
+ void drawRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight) override;
+ void drawPolyLine(sal_uInt32 nPoints, const Point* pPointArray) override;
+ void drawPolygon(sal_uInt32 nPoints, const Point* pPointArray) override;
+ void drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32* pPoints,
+ const Point** pPointArray) override;
+
+ bool drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon&, double fTransparency) override;
+
+ bool drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice, const basegfx::B2DPolygon&,
+ double fTransparency, double fLineWidth, const std::vector<double>* pStroke,
+ basegfx::B2DLineJoin, css::drawing::LineCap, double fMiterMinimumAngle,
+ bool bPixelSnapHairline) override;
+
+ bool drawPolyLineBezier(sal_uInt32 nPoints, const Point* pPointArray,
+ const PolyFlags* pFlagArray) override;
+
+ bool drawPolygonBezier(sal_uInt32 nPoints, const Point* pPointArray,
+ const PolyFlags* pFlagArray) override;
+
+ bool drawPolyPolygonBezier(sal_uInt32 nPoly, const sal_uInt32* pPoints,
+ const Point* const* pPointArray,
+ const PolyFlags* const* pFlagArray) override;
+
+ void copyArea(tools::Long nDestX, tools::Long nDestY, tools::Long nSrcX, tools::Long nSrcY,
+ tools::Long nSrcWidth, tools::Long nSrcHeight, bool bWindowInvalidate) override;
+
+ void copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics) override;
+
+ void drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap) override;
+
+ void drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap,
+ const SalBitmap& rMaskBitmap) override;
+
+ void drawMask(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap,
+ Color nMaskColor) override;
+
+ std::shared_ptr<SalBitmap> getBitmap(tools::Long nX, tools::Long nY, tools::Long nWidth,
+ tools::Long nHeight) override;
+
+ Color getPixel(tools::Long nX, tools::Long nY) override;
+
+ void invert(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
+ SalInvert nFlags) override;
+
+ void invert(sal_uInt32 nPoints, const Point* pPtAry, SalInvert nFlags) override;
+
+ bool drawEPS(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
+ void* pPtr, sal_uInt32 nSize) override;
+
+ bool blendBitmap(const SalTwoRect&, const SalBitmap& rBitmap) override;
+
+ bool blendAlphaBitmap(const SalTwoRect&, const SalBitmap& rSrcBitmap,
+ const SalBitmap& rMaskBitmap, const SalBitmap& rAlphaBitmap) override;
+
+ bool drawAlphaBitmap(const SalTwoRect&, const SalBitmap& rSourceBitmap,
+ const SalBitmap& rAlphaBitmap) override;
+
+ bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
+ const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
+ const SalBitmap* pAlphaBitmap, double fAlpha) override;
+
+ bool hasFastDrawTransformedBitmap() const override;
+
+ bool drawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
+ sal_uInt8 nTransparency) override;
+
+ bool drawGradient(const tools::PolyPolygon& rPolygon, const Gradient& rGradient) override;
+ bool implDrawGradient(basegfx::B2DPolyPolygon const& rPolyPolygon,
+ SalGradient const& rGradient) override;
+
+ bool supportsOperation(OutDevSupportType eType) const override;
+};
+
+class AquaSalGraphics : public SalGraphicsAutoDelegateToImpl
+{
+ AquaSharedAttributes maShared;
+ std::unique_ptr<AquaGraphicsBackend> mpBackend;
+
+ /// device resolution of this graphics
+ sal_Int32 mnRealDPIX;
+ sal_Int32 mnRealDPIY;
+
+ // Device Font settings
+ rtl::Reference<CoreTextStyle> mpTextStyle[MAX_FALLBACK];
+ RGBAColor maTextColor;
+ /// allows text to be rendered without antialiasing
+ bool mbNonAntialiasedText;
public:
AquaSalGraphics();
virtual ~AquaSalGraphics() override;
- bool IsPenVisible() const { return maLineColor.IsVisible(); }
- bool IsBrushVisible() const { return maFillColor.IsVisible(); }
-
void SetVirDevGraphics(CGLayerHolder const &rLayer, CGContextRef, int nBitDepth = 0);
#ifdef MACOSX
void initResolution( NSWindow* );
void copyResolution( AquaSalGraphics& );
void updateResolution();
- static float GetWindowScaling();
void SetWindowGraphics( AquaSalFrame* pFrame );
- bool IsWindowGraphics() const { return mbWindow; }
+ bool IsWindowGraphics() const { return maShared.mbWindow; }
void SetPrinterGraphics(CGContextRef, sal_Int32 nRealDPIX, sal_Int32 nRealDPIY);
- AquaSalFrame* getGraphicsFrame() const { return mpFrame; }
- void setGraphicsFrame( AquaSalFrame* pFrame ) { mpFrame = pFrame; }
+ AquaSalFrame* getGraphicsFrame() const { return maShared.mpFrame; }
+ void setGraphicsFrame( AquaSalFrame* pFrame ) { maShared.mpFrame = pFrame; }
#endif
- void ImplDrawPixel( tools::Long nX, tools::Long nY, const RGBAColor& ); // helper to draw single pixels
-
- bool CheckContext();
-
#ifdef MACOSX
void UpdateWindow( NSRect& ); // delivered in NSView coordinates
- void RefreshRect( const NSRect& );
+ void RefreshRect(const NSRect& rRect)
+ {
+ maShared.refreshRect(rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height);
+ }
#else
void RefreshRect( const CGRect& ) {}
#endif
- void RefreshRect(float lX, float lY, float lWidth, float lHeight);
- void SetState();
void UnsetState();
// InvalidateContext does an UnsetState and sets mrContext to 0
void InvalidateContext();
- virtual SalGraphicsImpl* GetImpl() const override;
+ AquaGraphicsBackend* getAquaGraphicsBackend() const
+ {
+ return mpBackend.get();
+ }
- virtual bool setClipRegion( const vcl::Region& ) override;
-
- // draw --> LineColor and FillColor and RasterOp and ClipRegion
- virtual void drawPixel( tools::Long nX, tools::Long nY ) override;
- virtual void drawPixel( tools::Long nX, tools::Long nY, Color nColor ) override;
- virtual void drawLine(
- tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2 ) override;
- virtual void drawRect(
- tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight ) override;
- virtual void drawPolyLine( sal_uInt32 nPoints, const Point* pPtAry ) override;
- virtual void drawPolygon( sal_uInt32 nPoints, const Point* pPtAry ) override;
- virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, const Point** pPtAry ) override;
- virtual bool drawPolyPolygon(
- const basegfx::B2DHomMatrix& rObjectToDevice,
- const basegfx::B2DPolyPolygon&,
- double fTransparency) override;
- virtual bool drawPolyLineBezier( sal_uInt32 nPoints, const Point* pPtAry, const PolyFlags* pFlgAry ) override;
- virtual bool drawPolygonBezier( sal_uInt32 nPoints, const Point* pPtAry, const PolyFlags* pFlgAry ) override;
- virtual bool drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints, const Point* const* pPtAry, const PolyFlags* const* pFlgAry ) override;
- virtual bool drawPolyLine(
- const basegfx::B2DHomMatrix& rObjectToDevice,
- const basegfx::B2DPolygon&,
- double fTransparency,
- double rLineWidth,
- const std::vector< double >* pStroke, // MM01
- basegfx::B2DLineJoin,
- css::drawing::LineCap eLineCap,
- double fMiterMinimumAngle,
- bool bPixelSnapHairline) override;
- virtual bool drawGradient( const tools::PolyPolygon&, const Gradient& ) override { return false; };
-
- // CopyArea --> No RasterOp, but ClipRegion
- virtual void copyArea( tools::Long nDestX, tools::Long nDestY, tools::Long nSrcX, tools::Long nSrcY, tools::Long nSrcWidth,
- tools::Long nSrcHeight, bool bWindowInvalidate ) override;
-
- // CopyBits and DrawBitmap --> RasterOp and ClipRegion
- // CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics
- virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) override;
- virtual void drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap ) override;
- virtual void drawBitmap( const SalTwoRect& rPosAry,
- const SalBitmap& rSalBitmap,
- const SalBitmap& rTransparentBitmap ) override;
- virtual void drawMask( const SalTwoRect& rPosAry,
- const SalBitmap& rSalBitmap,
- Color nMaskColor ) override;
-
- virtual std::shared_ptr<SalBitmap> getBitmap( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight ) override;
- virtual Color getPixel( tools::Long nX, tools::Long nY ) override;
-
- // invert --> ClipRegion (only Windows or VirDevs)
- virtual void invert( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, SalInvert nFlags) override;
- virtual void invert( sal_uInt32 nPoints, const Point* pPtAry, SalInvert nFlags ) override;
-
- virtual bool drawEPS( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, void* pPtr, sal_uInt32 nSize ) override;
-
- virtual bool blendBitmap( const SalTwoRect&,
- const SalBitmap& rBitmap ) override;
-
- virtual bool blendAlphaBitmap( const SalTwoRect&,
- const SalBitmap& rSrcBitmap,
- const SalBitmap& rMaskBitmap,
- const SalBitmap& rAlphaBitmap ) override;
-
- virtual bool drawAlphaBitmap( const SalTwoRect&,
- const SalBitmap& rSourceBitmap,
- const SalBitmap& rAlphaBitmap ) override;
-
- bool drawTransformedBitmap(
- const basegfx::B2DPoint& rNull,
- const basegfx::B2DPoint& rX,
- const basegfx::B2DPoint& rY,
- const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap,
- double fAlpha) override;
-
- virtual bool hasFastDrawTransformedBitmap() const override;
-
- virtual bool drawAlphaRect( tools::Long nX, tools::Long nY, tools::Long nWidth,
- tools::Long nHeight, sal_uInt8 nTransparency ) override;
+ virtual SalGraphicsImpl* GetImpl() const override;
#ifdef MACOSX
@@ -318,37 +467,11 @@ protected:
virtual bool getNativeControlRegion( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState nState,
const ImplControlValue& aValue, const OUString& aCaption,
tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion ) override;
-
- void copyScaledArea( tools::Long nDestX, tools::Long nDestY, tools::Long nSrcX, tools::Long nSrcY,
- tools::Long nSrcWidth, tools::Long nSrcHeight, SalGraphics* pSrcGraphics );
#endif
public:
// get device resolution
virtual void GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) override;
- // get the depth of the device
- virtual sal_uInt16 GetBitCount() const override;
- // get the width of the device
- virtual tools::Long GetGraphicsWidth() const override;
-
- // set the clip region to empty
- virtual void ResetClipRegion() override;
-
- // set the line color to transparent (= don't draw lines)
- virtual void SetLineColor() override;
- // set the line color to a specific color
- virtual void SetLineColor( Color nColor ) override;
- // set the fill color to transparent (= don't fill)
- virtual void SetFillColor() override;
- // set the fill color to a specific color, shapes will be
- // filled accordingly
- virtual void SetFillColor( Color nColor ) override;
- // enable/disable XOR drawing
- virtual void SetXORMode( bool bSet, bool bInvertOnly ) override;
- // set line color for raster operations
- virtual void SetROPLineColor( SalROPColor nROPColor ) override;
- // set fill color for raster operations
- virtual void SetROPFillColor( SalROPColor nROPColor ) override;
// set the text color to a specific color
virtual void SetTextColor( Color nColor ) override;
// set the font
@@ -401,19 +524,11 @@ public:
virtual std::unique_ptr<GenericSalLayout>
GetTextLayout(int nFallbackLevel) override;
virtual void DrawTextLayout( const GenericSalLayout& ) override;
- virtual bool supportsOperation( OutDevSupportType ) const override;
- virtual OUString getRenderBackendName() const override { return "aqua"; }
virtual SystemGraphicsData
GetGraphicsData() const override;
private:
- // differences between VCL, Quartz and kHiThemeOrientation coordinate systems
- // make some graphics seem to be vertically-mirrored from a VCL perspective
- bool IsFlipped() const;
-
- void ApplyXorContext();
- void Pattern50Fill();
UInt32 getState( ControlState nState );
UInt32 getTrackState( ControlState nState );
static bool GetRawFontData( const PhysicalFontFace* pFontData,
@@ -421,16 +536,6 @@ private:
bool* pJustCFF );
};
-// --- some trivial inlines
-
-#ifdef MACOSX
-
-inline void AquaSalGraphics::RefreshRect( const NSRect& rRect )
-{
- RefreshRect( rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height );
-}
-
-#endif
#endif // INCLUDED_VCL_INC_QUARTZ_SALGDI_H
diff --git a/vcl/ios/dummies.cxx b/vcl/ios/dummies.cxx
index d62609dc95bf..135a534243fd 100644
--- a/vcl/ios/dummies.cxx
+++ b/vcl/ios/dummies.cxx
@@ -110,11 +110,6 @@ void SalGenericInstance::jobEndedPrinterUpdate()
{
}
-bool AquaSalGraphics::drawEPS( long, long, long, long, void*, sal_uInt32 )
-{
- return false;
-}
-
using namespace psp;
GenericUnixSalData::GenericUnixSalData(GenericUnixSalDataType const t, SalInstance *const pInstance)
diff --git a/vcl/ios/salios.cxx b/vcl/ios/salios.cxx
index fc925b61cdf3..ac11faff3072 100644
--- a/vcl/ios/salios.cxx
+++ b/vcl/ios/salios.cxx
@@ -88,13 +88,8 @@ bool QuartzSalBitmap::Create(CGLayerHolder const & rLayerHolder, int nBitmapBits
// From salgdicommon.cxx
-void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGraphics )
+void AquaGraphicsBackend::copyBits(const SalTwoRect& rPosAry, SalGraphics *pSrcGraphics)
{
-
- if( !pSrcGraphics )
- {
- pSrcGraphics = this;
- }
//from unix salgdi2.cxx
//[FIXME] find a better way to prevent calc from crashing when width and height are negative
if( rPosAry.mnSrcWidth <= 0 ||
@@ -106,12 +101,21 @@ void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGrap
}
// If called from idle layout, maContextHolder.get() is NULL, no idea what to do
- if (!maContextHolder.isSet())
+ if (!mrShared.maContextHolder.isSet())
return;
+ AquaSharedAttributes* pSrcShared = nullptr;
+
+ if (pSrcGraphics)
+ {
+ AquaSalGraphics* pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics);
+ pSrcShared = &pSrc->getAquaGraphicsBackend()->mrShared;
+ }
+ else
+ pSrcShared = &mrShared;
+
// accelerate trivial operations
- /*const*/ AquaSalGraphics* pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics);
- const bool bSameGraphics = (this == pSrc);
+ const bool bSameGraphics = (pSrcShared == &mrShared);
if( bSameGraphics &&
(rPosAry.mnSrcWidth == rPosAry.mnDestWidth) &&
@@ -129,26 +133,27 @@ void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGrap
return;
}
- ApplyXorContext();
- pSrc->ApplyXorContext();
+ mrShared.applyXorContext();
+ if (!bSameGraphics)
+ pSrcShared->applyXorContext();
- SAL_WARN_IF (!pSrc->maLayer.isSet(), "vcl.quartz",
+ SAL_WARN_IF (!pSrcShared->maLayer.isSet(), "vcl.quartz",
"AquaSalGraphics::copyBits() from non-layered graphics this=" << this);
const CGPoint aDstPoint = CGPointMake(+rPosAry.mnDestX - rPosAry.mnSrcX, rPosAry.mnDestY - rPosAry.mnSrcY);
if ((rPosAry.mnSrcWidth == rPosAry.mnDestWidth &&
rPosAry.mnSrcHeight == rPosAry.mnDestHeight) &&
- (!mnBitmapDepth || (aDstPoint.x + pSrc->mnWidth) <= mnWidth)
- && pSrc->maLayer.isSet()) // workaround for a Quartz crash
+ (!mrShared.mnBitmapDepth || (aDstPoint.x + pSrcShared->mnWidth) <= mrShared.mnWidth)
+ && pSrcShared->maLayer.isSet()) // workaround for a Quartz crash
{
// in XOR mode the drawing context is redirected to the XOR mask
// if source and target are identical then copyBits() paints onto the target context though
- CGContextHolder aCopyContext = maContextHolder;
- if( mpXorEmulation && mpXorEmulation->IsEnabled() )
+ CGContextHolder aCopyContext = mrShared.maContextHolder;
+ if (mrShared.mpXorEmulation && mrShared.mpXorEmulation->IsEnabled())
{
- if( pSrcGraphics == this )
+ if (bSameGraphics)
{
- aCopyContext.set(mpXorEmulation->GetTargetContext());
+ aCopyContext.set(mrShared.mpXorEmulation->GetTargetContext());
}
}
aCopyContext.saveState();
@@ -158,43 +163,47 @@ void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGrap
// draw at new destination
// NOTE: flipped drawing gets disabled for this, else the subimage would be drawn upside down
- if( pSrc->IsFlipped() )
+ if (pSrcShared->isFlipped())
{
- CGContextTranslateCTM( aCopyContext.get(), 0, +mnHeight );
- CGContextScaleCTM( aCopyContext.get(), +1, -1 );
+ CGContextTranslateCTM(aCopyContext.get(), 0, +mrShared.mnHeight);
+ CGContextScaleCTM(aCopyContext.get(), +1, -1);
}
// TODO: pSrc->size() != this->size()
- CGContextDrawLayerAtPoint(aCopyContext.get(), aDstPoint, pSrc->maLayer.get());
+ CGContextDrawLayerAtPoint(aCopyContext.get(), aDstPoint, pSrcShared->maLayer.get());
aCopyContext.restoreState();
// mark the destination rectangle as updated
- RefreshRect( aDstRect );
+ refreshRect(aDstRect);
}
else
{
- std::shared_ptr<SalBitmap> pBitmap = pSrc->getBitmap( rPosAry.mnSrcX, rPosAry.mnSrcY,
- rPosAry.mnSrcWidth, rPosAry.mnSrcHeight );
- if( pBitmap )
+ std::shared_ptr<SalBitmap> pBitmap;
+ if (pSrcGraphics)
+ pBitmap = pSrcGraphics->GetImpl()->getBitmap(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight);
+ else
+ pBitmap = getBitmap(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight);
+
+ if (pBitmap)
{
SalTwoRect aPosAry( rPosAry );
aPosAry.mnSrcX = 0;
aPosAry.mnSrcY = 0;
- drawBitmap( aPosAry, *pBitmap );
+ drawBitmap(aPosAry, *pBitmap);
}
}
}
-void AquaSalGraphics::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY,
+void AquaGraphicsBackend::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY,
tools::Long nSrcWidth, tools::Long nSrcHeight, bool /*bWindowInvalidate*/)
{
- SAL_WARN_IF (!maLayer.isSet(), "vcl.quartz",
+ SAL_WARN_IF (!mrShared.maLayer.isSet(), "vcl.quartz",
"AquaSalGraphics::copyArea() for non-layered graphics this=" << this);
- if (!maLayer.isSet())
+ if (!mrShared.maLayer.isSet())
return;
- float fScale = maLayer.getScale();
+ float fScale = mrShared.maLayer.getScale();
tools::Long nScaledSourceX = nSrcX * fScale;
tools::Long nScaledSourceY = nSrcY * fScale;
@@ -205,17 +214,17 @@ void AquaSalGraphics::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long
tools::Long nScaledSourceWidth = nSrcWidth * fScale;
tools::Long nScaledSourceHeight = nSrcHeight * fScale;
- ApplyXorContext();
+ mrShared.applyXorContext();
- maContextHolder.saveState();
+ mrShared.maContextHolder.saveState();
// in XOR mode the drawing context is redirected to the XOR mask
// copyArea() always works on the target context though
- CGContextRef xCopyContext = maContextHolder.get();
+ CGContextRef xCopyContext = mrShared.maContextHolder.get();
- if( mpXorEmulation && mpXorEmulation->IsEnabled() )
+ if (mrShared.mpXorEmulation && mrShared.mpXorEmulation->IsEnabled())
{
- xCopyContext = mpXorEmulation->GetTargetContext();
+ xCopyContext = mrShared.mpXorEmulation->GetTargetContext();
}
// If we have a scaled layer, we need to revert the scaling or else
@@ -227,7 +236,7 @@ void AquaSalGraphics::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long
// e.g. on OSX>=10.5 only this situation causes problems:
// mnBitmapDepth && (aDstPoint.x + pSrc->mnWidth) > mnWidth
- CGLayerHolder sSourceLayerHolder(maLayer);
+ CGLayerHolder sSourceLayerHolder(mrShared.maLayer);
{
const CGSize aSrcSize = CGSizeMake(nScaledSourceWidth, nScaledSourceHeight);
sSourceLayerHolder.set(CGLayerCreateWithContext(xCopyContext, aSrcSize, nullptr));
@@ -235,15 +244,15 @@ void AquaSalGraphics::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long
const CGContextRef xSrcContext = CGLayerGetContext(sSourceLayerHolder.get());
CGPoint aSrcPoint = CGPointMake(-nScaledSourceX, -nScaledSourceY);
- if( IsFlipped() )
+ if (mrShared.isFlipped())
{
- CGContextTranslateCTM( xSrcContext, 0, +nScaledSourceHeight );
- CGContextScaleCTM( xSrcContext, +1, -1 );
- aSrcPoint.y = (nScaledSourceY + nScaledSourceHeight) - (mnHeight * fScale);
+ CGContextTranslateCTM(xSrcContext, 0, +nScaledSourceHeight);
+ CGContextScaleCTM(xSrcContext, +1, -1);
+ aSrcPoint.y = (nScaledSourceY + nScaledSourceHeight) - (mrShared.mnHeight * fScale);
}
CGContextSetBlendMode(xSrcContext, kCGBlendModeCopy);
- CGContextDrawLayerAtPoint(xSrcContext, aSrcPoint, maLayer.get());
+ CGContextDrawLayerAtPoint(xSrcContext, aSrcPoint, mrShared.maLayer.get());
}
// draw at new destination
@@ -251,15 +260,16 @@ void AquaSalGraphics::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long
CGContextSetBlendMode(xCopyContext, kCGBlendModeCopy);
CGContextDrawLayerInRect(xCopyContext, aTargetRect, sSourceLayerHolder.get());
- maContextHolder.restoreState();
+ mrShared.maContextHolder.restoreState();
// cleanup
- if (sSourceLayerHolder.get() != maLayer.get())
+ if (sSourceLayerHolder.get() != mrShared.maLayer.get())
{
CGLayerRelease(sSourceLayerHolder.get());
}
+
// mark the destination rectangle as updated
- RefreshRect( nDstX, nDstY, nSrcWidth, nSrcHeight );
+ mrShared.refreshRect(nDstX, nDstY, nSrcWidth, nSrcHeight);
}
void AquaSalGraphics::SetVirDevGraphics(CGLayerHolder const & rLayer, CGContextRef xContext,
@@ -267,52 +277,52 @@ void AquaSalGraphics::SetVirDevGraphics(CGLayerHolder const & rLayer, CGContextR
{
SAL_INFO( "vcl.quartz", "SetVirDevGraphics() this=" << this << " layer=" << rLayer.get() << " context=" << xContext );
- mbPrinter = false;
- mbVirDev = true;
+ maShared.mbPrinter = false;
+ maShared.mbVirDev = true;
// set graphics properties
- maLayer = rLayer;
- maContextHolder.set(xContext);
+ maShared.maLayer = rLayer;
+ maShared.maContextHolder.set(xContext);
- mnBitmapDepth = nBitmapDepth;
+ maShared.mnBitmapDepth = nBitmapDepth;
- mbForeignContext = xContext != NULL;
+ maShared.mbForeignContext = xContext != NULL;
// return early if the virdev is being destroyed
- if( !xContext )
+ if (!xContext)
return;
// get new graphics properties
- if (!maLayer.isSet())
+ if (!maShared.maLayer.isSet())
{
- mnWidth = CGBitmapContextGetWidth( maContextHolder.get() );
- mnHeight = CGBitmapContextGetHeight( maContextHolder.get() );
+ maShared.mnWidth = CGBitmapContextGetWidth(maShared.maContextHolder.get());
+ maShared.mnHeight = CGBitmapContextGetHeight(maShared.maContextHolder.get());
}
else
{
- const CGSize aSize = CGLayerGetSize(maLayer.get());
- mnWidth = static_cast<int>(aSize.width);
- mnHeight = static_cast<int>(aSize.height);
+ const CGSize aSize = CGLayerGetSize(maShared.maLayer.get());
+ maShared.mnWidth = static_cast<int>(aSize.width);
+ maShared.mnHeight = static_cast<int>(aSize.height);
}
// prepare graphics for drawing
const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace;
- CGContextSetFillColorSpace( maContextHolder.get(), aCGColorSpace );
- CGContextSetStrokeColorSpace( maContextHolder.get(), aCGColorSpace );
+ CGContextSetFillColorSpace(maShared.maContextHolder.get(), aCGColorSpace);
+ CGContextSetStrokeColorSpace(maShared.maContextHolder.get(), aCGColorSpace);
// re-enable XorEmulation for the new context
- if( mpXorEmulation )
+ if (maShared.mpXorEmulation)
{
- mpXorEmulation->SetTarget(mnWidth, mnHeight, mnBitmapDepth, maContextHolder.get(), maLayer.get());
- if( mpXorEmulation->IsEnabled() )
+ maShared.mpXorEmulation->SetTarget(maShared.mnWidth, maShared.mnHeight, maShared.mnBitmapDepth, maShared.maContextHolder.get(), maShared.maLayer.get());
+ if (maShared.mpXorEmulation->IsEnabled())
{
- maContextHolder.set(mpXorEmulation->GetMaskContext());
+ maShared.maContextHolder.set(maShared.mpXorEmulation->GetMaskContext());
}
}
// initialize stack of CGContext states
- maContextHolder.saveState();
- SetState();
+ maShared.maContextHolder.saveState();
+ maShared.setState();
}
/// From salvd.cxx
diff --git a/vcl/osx/salgdiutils.cxx b/vcl/osx/salgdiutils.cxx
index f3ddd946f699..81210c8e876c 100644
--- a/vcl/osx/salgdiutils.cxx
+++ b/vcl/osx/salgdiutils.cxx
@@ -46,7 +46,9 @@
static bool bWindowScaling = false;
static float fWindowScale = 1.0f;
-float AquaSalGraphics::GetWindowScaling()
+namespace sal::aqua
+{
+float getWindowScaling()
{
if (!bWindowScaling)
{
@@ -65,38 +67,35 @@ float AquaSalGraphics::GetWindowScaling()
}
return fWindowScale;
}
+} // end aqua
void AquaSalGraphics::SetWindowGraphics( AquaSalFrame* pFrame )
{
- mpFrame = pFrame;
- mbWindow = true;
- mbPrinter = false;
- mbVirDev = false;
+ maShared.mpFrame = pFrame;
+ maShared.mbWindow = true;
+ maShared.mbPrinter = false;
+ maShared.mbVirDev = false;
}
void AquaSalGraphics::SetPrinterGraphics( CGContextRef xContext, sal_Int32 nDPIX, sal_Int32 nDPIY )
{
- mbWindow = false;
- mbPrinter = true;
- mbVirDev = false;
+ maShared.mbWindow = false;
+ maShared.mbPrinter = true;
+ maShared.mbVirDev = false;
- maContextHolder.set(xContext);
+ maShared.maContextHolder.set(xContext);
mnRealDPIX = nDPIX;
mnRealDPIY = nDPIY;
// a previously set clip path is now invalid
- if( mxClipPath )
- {
- CGPathRelease( mxClipPath );
- mxClipPath = nullptr;
- }
+ maShared.unsetClipPath();
- if (maContextHolder.isSet())
+ if (maShared.maContextHolder.isSet())
{
- CGContextSetFillColorSpace( maContextHolder.get(), GetSalData()->mxRGBSpace );
- CGContextSetStrokeColorSpace( maContextHolder.get(), GetSalData()->mxRGBSpace );
- CGContextSaveGState( maContextHolder.get() );
- SetState();
+ CGContextSetFillColorSpace( maShared.maContextHolder.get(), GetSalData()->mxRGBSpace );
+ CGContextSetStrokeColorSpace( maShared.maContextHolder.get(), GetSalData()->mxRGBSpace );
+ CGContextSaveGState( maShared.maContextHolder.get() );
+ maShared.setState();
}
}
@@ -104,50 +103,46 @@ void AquaSalGraphics::InvalidateContext()
{
UnsetState();
- CGContextRelease(maContextHolder.get());
- CGContextRelease(maBGContextHolder.get());
- CGContextRelease(maCSContextHolder.get());
+ CGContextRelease(maShared.maContextHolder.get());
+ CGContextRelease(maShared.maBGContextHolder.get());
+ CGContextRelease(maShared.maCSContextHolder.get());
- maContextHolder.set(nullptr);
- maCSContextHolder.set(nullptr);
- maBGContextHolder.set(nullptr);
+ maShared.maContextHolder.set(nullptr);
+ maShared.maCSContextHolder.set(nullptr);
+ maShared.maBGContextHolder.set(nullptr);
}
void AquaSalGraphics::UnsetState()
{
- if (maBGContextHolder.isSet())
- {
- CGContextRelease(maBGContextHolder.get());
- maBGContextHolder.set(nullptr);
- }
- if (maCSContextHolder.isSet())
+ if (maShared.maBGContextHolder.isSet())
{
- CGContextRelease(maCSContextHolder.get());
- maBGContextHolder.set(nullptr);
+ CGContextRelease(maShared.maBGContextHolder.get());
+ maShared.maBGContextHolder.set(nullptr);
}
- if (maContextHolder.isSet())
+ if (maShared.maCSContextHolder.isSet())
{
- maContextHolder.restoreState();
- maContextHolder.set(nullptr);
+ CGContextRelease(maShared.maCSContextHolder.get());
+ maShared.maBGContextHolder.set(nullptr);
}
- if( mxClipPath )
+ if (maShared.maContextHolder.isSet())
{
- CGPathRelease( mxClipPath );
- mxClipPath = nullptr;
+ maShared.maContextHolder.restoreState();
+ maShared.maContextHolder.set(nullptr);
}
+ maShared.unsetState();
}
/**
* (re-)create the off-screen maLayer we render everything to if
* necessary: eg. not initialized yet, or it has an incorrect size.
*/
-bool AquaSalGraphics::CheckContext()
+bool AquaSharedAttributes::checkContext()
{
if (mbWindow && mpFrame && (mpFrame->getNSWindow() || Application::IsBitmapRendering()))
{
const unsigned int nWidth = mpFrame->maGeometry.nWidth;
const unsigned int nHeight = mpFrame->maGeometry.nHeight;
- const float fScale = GetWindowScaling();
+ const float fScale = sal::aqua::getWindowScaling();
CGLayerRef rReleaseLayer = nullptr;
// check if a new drawing context is needed (e.g. after a resize)
@@ -218,7 +213,7 @@ bool AquaSalGraphics::CheckContext()
// apply a scale matrix so everything is auto-magically scaled
CGContextScaleCTM(maContextHolder.get(), fScale, fScale);
maContextHolder.saveState();
- SetState();
+ setState();
// re-enable XOR emulation for the new context
if (mpXorEmulation)
@@ -239,19 +234,19 @@ bool AquaSalGraphics::CheckContext()
*/
void AquaSalGraphics::UpdateWindow( NSRect& )
{
- if( !mpFrame )
+ if (!maShared.mpFrame)
{
return;
}
NSGraphicsContext* pContext = [NSGraphicsContext currentContext];
- if (maLayer.isSet() && pContext != nullptr)
+ if (maShared.maLayer.isSet() && pContext != nullptr)
{
CGContextHolder rCGContextHolder([pContext CGContext]);
rCGContextHolder.saveState();
- CGMutablePathRef rClip = mpFrame->getClipPath();
+ CGMutablePathRef rClip = maShared.mpFrame->getClipPath();
if (rClip)
{
CGContextBeginPath(rCGContextHolder.get());
@@ -259,16 +254,16 @@ void AquaSalGraphics::UpdateWindow( NSRect& )
CGContextClip(rCGContextHolder.get());
}
- ApplyXorContext();
+ maShared.applyXorContext();
- const CGSize aSize = maLayer.getSizePoints();
+ const CGSize aSize = maShared.maLayer.getSizePoints();
const CGRect aRect = CGRectMake(0, 0, aSize.width, aSize.height);
- const CGRect aRectPoints = { CGPointZero, maLayer.getSizePixels() };
- CGContextSetBlendMode(maCSContextHolder.get(), kCGBlendModeCopy);
- CGContextDrawLayerInRect(maCSContextHolder.get(), aRectPoints, maLayer.get());
+ const CGRect aRectPoints = { CGPointZero, maShared.maLayer.getSizePixels() };
+ CGContextSetBlendMode(maShared.maCSContextHolder.get(), kCGBlendModeCopy);
+ CGContextDrawLayerInRect(maShared.maCSContextHolder.get(), aRectPoints, maShared.maLayer.get());
- CGImageRef img = CGBitmapContextCreateImage(maCSContextHolder.get());
- CGImageRef displayColorSpaceImage = CGImageCreateCopyWithColorSpace(img, [[mpFrame->getNSWindow() colorSpace] CGColorSpace]);
+ CGImageRef img = CGBitmapContextCreateImage(maShared.maCSContextHolder.get());
+ CGImageRef displayColorSpaceImage = CGImageCreateCopyWithColorSpace(img, [[maShared.mpFrame->getNSWindow() colorSpace] CGColorSpace]);
CGContextSetBlendMode(rCGContextHolder.get(), kCGBlendModeCopy);
CGContextDrawImage(rCGContextHolder.get(), aRect, displayColorSpaceImage);
@@ -279,7 +274,7 @@ void AquaSalGraphics::UpdateWindow( NSRect& )
}
else
{
- SAL_WARN_IF( !mpFrame->mbInitShow, "vcl", "UpdateWindow called on uneligible graphics" );
+ SAL_WARN_IF(!maShared.mpFrame->mbInitShow, "vcl", "UpdateWindow called on uneligible graphics");
}
}
diff --git a/vcl/osx/salmacos.cxx b/vcl/osx/salmacos.cxx
index f6403dea2725..fa2520f056a6 100644
--- a/vcl/osx/salmacos.cxx
+++ b/vcl/osx/salmacos.cxx
@@ -96,29 +96,36 @@ bool QuartzSalBitmap::Create(CGLayerHolder const & rLayerHolder, int nBitmapBits
// From salgdicommon.cxx
-void AquaSalGraphics::copyBits(const SalTwoRect &rPosAry, SalGraphics *pSrcGraphics)
+void AquaGraphicsBackend::copyBits(const SalTwoRect &rPosAry, SalGraphics *pSrcGraphics)
{
- if (!pSrcGraphics)
- pSrcGraphics = this;
- AquaSalGraphics *pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics);
+ AquaSharedAttributes* pSrcShared = nullptr;
+
+ if (pSrcGraphics)
+ {
+ AquaSalGraphics* pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics);
+ pSrcShared = &pSrc->getAquaGraphicsBackend()->mrShared;
+ }
+ else
+ pSrcShared = &mrShared;
+
if (rPosAry.mnSrcWidth <= 0 || rPosAry.mnSrcHeight <= 0 || rPosAry.mnDestWidth <= 0 || rPosAry.mnDestHeight <= 0)
return;
- if (!maContextHolder.isSet())
+ if (!mrShared.maContextHolder.isSet())
return;
- SAL_WARN_IF (!pSrc->maLayer.isSet(), "vcl.quartz", "AquaSalGraphics::copyBits() from non-layered graphics this=" << this);
+ SAL_WARN_IF (!pSrcShared->maLayer.isSet(), "vcl.quartz", "AquaSalGraphics::copyBits() from non-layered graphics this=" << this);
// Layered graphics are copied by AquaSalGraphics::copyScaledArea() which is able to consider the layer's scaling.
- if (pSrc->maLayer.isSet())
+ if (pSrcShared->maLayer.isSet())
copyScaledArea(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY,
- rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, pSrcGraphics);
+ rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, pSrcShared);
else
{
- ApplyXorContext();
- pSrc->ApplyXorContext();
- std::shared_ptr<SalBitmap> pBitmap = pSrc->getBitmap(rPosAry.mnSrcX, rPosAry.mnSrcY,
- rPosAry.mnSrcWidth, rPosAry.mnSrcHeight);
+ mrShared.applyXorContext();
+ pSrcShared->applyXorContext();
+ std::shared_ptr<SalBitmap> pBitmap = pSrcGraphics->GetImpl()->getBitmap(rPosAry.mnSrcX, rPosAry.mnSrcY,
+ rPosAry.mnSrcWidth, rPosAry.mnSrcHeight);
if (pBitmap)
{
SalTwoRect aPosAry(rPosAry);
@@ -129,34 +136,30 @@ void AquaSalGraphics::copyBits(const SalTwoRect &rPosAry, SalGraphics *pSrcGraph
}
}
-void AquaSalGraphics::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY,
+void AquaGraphicsBackend::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY,
tools::Long nSrcWidth, tools::Long nSrcHeight, bool)
{
- if (!maContextHolder.isSet())
+ if (!mrShared.maContextHolder.isSet())
return;
// Functionality is implemented in protected member function AquaSalGraphics::copyScaledArea() which requires an additional
// parameter of type SalGraphics to be used in AquaSalGraphics::copyBits() too.
- copyScaledArea(nDstX, nDstY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, this);
+ copyScaledArea(nDstX, nDstY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, &mrShared);
}
-void AquaSalGraphics::copyScaledArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY,
- tools::Long nSrcWidth, tools::Long nSrcHeight, SalGraphics *pSrcGraphics)
+void AquaGraphicsBackend::copyScaledArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY,
+ tools::Long nSrcWidth, tools::Long nSrcHeight, AquaSharedAttributes* pSrcShared)
{
- if (!pSrcGraphics)
- pSrcGraphics = this;
- AquaSalGraphics *pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics);
-
- SAL_WARN_IF(!maLayer.isSet(), "vcl.quartz",
+ SAL_WARN_IF(!mrShared.maLayer.isSet(), "vcl.quartz",
"AquaSalGraphics::copyScaledArea() without graphics context or for non-layered graphics this=" << this);
- if (!maContextHolder.isSet() || !maLayer.isSet())
+ if (!mrShared.maContextHolder.isSet() || !mrShared.maLayer.isSet())
return;
// Determine scaled geometry of source and target area assuming source and target area have the same scale
- float fScale = maLayer.getScale();
+ float fScale = mrShared.maLayer.getScale();
CGFloat nScaledSourceX = nSrcX * fScale;
CGFloat nScaledSourceY = nSrcY * fScale;
CGFloat nScaledTargetX = nDstX * fScale;
@@ -166,11 +169,11 @@ void AquaSalGraphics::copyScaledArea(tools::Long nDstX, tools::Long nDstY,tools:
// Apply XOR context and get copy context from current graphics context or XOR context
- ApplyXorContext();
- maContextHolder.saveState();
- CGContextRef xCopyContext = maContextHolder.get();
- if (mpXorEmulation && mpXorEmulation->IsEnabled())
- xCopyContext = mpXorEmulation->GetTargetContext();
+ mrShared.applyXorContext();
+ mrShared.maContextHolder.saveState();
+ CGContextRef xCopyContext = mrShared.maContextHolder.get();
+ if (mrShared.mpXorEmulation && mrShared.mpXorEmulation->IsEnabled())
+ xCopyContext = mrShared.mpXorEmulation->GetTargetContext();
// Set scale matrix of copy context to consider layer scaling
@@ -179,19 +182,19 @@ void AquaSalGraphics::copyScaledArea(tools::Long nDstX, tools::Long nDstY,tools:
// Creating an additional layer is required for drawing with the required scale and extent at the drawing destination
// thereafter.
- CGLayerHolder aSourceLayerHolder(pSrc->maLayer);
+ CGLayerHolder aSourceLayerHolder(pSrcShared->maLayer);
const CGSize aSourceSize = CGSizeMake(nScaledSourceWidth, nScaledSourceHeight);
aSourceLayerHolder.set(CGLayerCreateWithContext(xCopyContext, aSourceSize, nullptr));
const CGContextRef xSourceContext = CGLayerGetContext(aSourceLayerHolder.get());
CGPoint aSrcPoint = CGPointMake(-nScaledSourceX, -nScaledSourceY);
- if (pSrc->IsFlipped())
+ if (pSrcShared->isFlipped())
{
CGContextTranslateCTM(xSourceContext, 0, nScaledSourceHeight);
CGContextScaleCTM(xSourceContext, 1, -1);
- aSrcPoint.y = nScaledSourceY + nScaledSourceHeight - mnHeight * fScale;
+ aSrcPoint.y = nScaledSourceY + nScaledSourceHeight - mrShared.mnHeight * fScale;
}
CGContextSetBlendMode(xSourceContext, kCGBlendModeCopy);
- CGContextDrawLayerAtPoint(xSourceContext, aSrcPoint, pSrc->maLayer.get());
+ CGContextDrawLayerAtPoint(xSourceContext, aSrcPoint, pSrcShared->maLayer.get());
// Copy source area from additional layer to target area
@@ -201,10 +204,11 @@ void AquaSalGraphics::copyScaledArea(tools::Long nDstX, tools::Long nDstY,tools:
// Housekeeping on exit
- maContextHolder.restoreState();
- if (aSourceLayerHolder.get() != maLayer.get())
+ mrShared.maContextHolder.restoreState();
+ if (aSourceLayerHolder.get() != mrShared.maLayer.get())
CGLayerRelease(aSourceLayerHolder.get());
- RefreshRect(nDstX, nDstY, nSrcWidth, nSrcHeight);
+
+ mrShared.refreshRect(nDstX, nDstY, nSrcWidth, nSrcHeight);
}
void AquaSalGraphics::SetVirDevGraphics(CGLayerHolder const &rLayer, CGContextRef xContext, int nBitmapDepth)
@@ -214,61 +218,61 @@ void AquaSalGraphics::SetVirDevGraphics(CGLayerHolder const &rLayer, CGContextRe
// Set member variables
InvalidateContext();
- mbWindow = false;
- mbPrinter = false;
- mbVirDev = true;
- maLayer = rLayer;
- mnBitmapDepth = nBitmapDepth;
+ maShared.mbWindow = false;
+ maShared.mbPrinter = false;
+ maShared.mbVirDev = true;
+ maShared.maLayer = rLayer;
+ maShared.mnBitmapDepth = nBitmapDepth;
- // Get size and scale from layer if set else from bitmap and AquaSalGraphics::GetWindowScaling(), which is used to determine
+ // Get size and scale from layer if set else from bitmap and sal::aqua::getWindowScaling(), which is used to determine
// scaling for direct graphics output too
CGSize aSize;
float fScale;
- if (maLayer.isSet())
+ if (maShared.maLayer.isSet())
{
- maContextHolder.set(CGLayerGetContext(maLayer.get()));
- aSize = CGLayerGetSize(maLayer.get());
- fScale = maLayer.getScale();
+ maShared.maContextHolder.set(CGLayerGetContext(maShared.maLayer.get()));
+ aSize = CGLayerGetSize(maShared.maLayer.get());
+ fScale = maShared.maLayer.getScale();
}
else
{
- maContextHolder.set(xContext);
+ maShared.maContextHolder.set(xContext);
if (!xContext)
return;
aSize.width = CGBitmapContextGetWidth(xContext);
aSize.height = CGBitmapContextGetHeight(xContext);
- fScale = GetWindowScaling();
+ fScale = sal::aqua::getWindowScaling();
}
- mnWidth = aSize.width / fScale;
- mnHeight = aSize.height / fScale;
+ maShared.mnWidth = aSize.width / fScale;
+ maShared.mnHeight = aSize.height / fScale;
// Set color space for fill and stroke
CGColorSpaceRef aColorSpace = GetSalData()->mxRGBSpace;
- CGContextSetFillColorSpace(maContextHolder.get(), aColorSpace);
- CGContextSetStrokeColorSpace(maContextHolder.get(), aColorSpace);
+ CGContextSetFillColorSpace(maShared.maContextHolder.get(), aColorSpace);
+ CGContextSetStrokeColorSpace(maShared.maContextHolder.get(), aColorSpace);
// Apply scale matrix to virtual device graphics
- CGContextScaleCTM(maContextHolder.get(), fScale, fScale);
+ CGContextScaleCTM(maShared.maContextHolder.get(), fScale, fScale);
// Apply XOR emulation if required
- if (mpXorEmulation)
+ if (maShared.mpXorEmulation)
{
- mpXorEmulation->SetTarget(mnWidth, mnHeight, mnBitmapDepth, maContextHolder.get(), maLayer.get());
- if (mpXorEmulation->IsEnabled())
- maContextHolder.set(mpXorEmulation->GetMaskContext());
+ maShared.mpXorEmulation->SetTarget(maShared.mnWidth, maShared.mnHeight, maShared.mnBitmapDepth, maShared.maContextHolder.get(), maShared.maLayer.get());
+ if (maShared.mpXorEmulation->IsEnabled())
+ maShared.maContextHolder.set(maShared.mpXorEmulation->GetMaskContext());
}
// Housekeeping on exit
- maContextHolder.saveState();
- SetState();
+ maShared.maContextHolder.saveState();
+ maShared.setState();
SAL_INFO("vcl.quartz", "SetVirDevGraphics() this=" << this <<
- " (" << mnWidth << "x" << mnHeight << ") fScale=" << fScale << " mnBitmapDepth=" << mnBitmapDepth);
+ " (" << maShared.mnWidth << "x" << maShared.mnHeight << ") fScale=" << fScale << " mnBitmapDepth=" << maShared.mnBitmapDepth);
}
// From salvd.cxx
@@ -277,7 +281,7 @@ void AquaSalVirtualDevice::Destroy()
{
SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::Destroy() this=" << this << " mbForeignContext=" << mbForeignContext );
- if( mbForeignContext )
+ if (mbForeignContext)
{
// Do not delete mxContext that we have received from outside VCL
maLayer.set(nullptr);
@@ -327,11 +331,11 @@ bool AquaSalVirtualDevice::SetSize(tools::Long nDX, tools::Long nDY)
Destroy();
// Prepare new graphics context for initialization, use scaling independent of prior graphics context calculated by
- // AquaSalGraphics::GetWindowScaling(), which is used to determine scaling for direct graphics output too
+ // sal::aqua::getWindowScaling(), which is used to determine scaling for direct graphics output too
mnWidth = nDX;
mnHeight = nDY;
- fScale = AquaSalGraphics::GetWindowScaling();
+ fScale = sal::aqua::getWindowScaling();
CGColorSpaceRef aColorSpace;
uint32_t nFlags;
if (mnBitmapDepth && (mnBitmapDepth < 16))
diff --git a/vcl/osx/salnativewidgets.cxx b/vcl/osx/salnativewidgets.cxx
index bc132ee88d16..589feec62208 100644
--- a/vcl/osx/salnativewidgets.cxx
+++ b/vcl/osx/salnativewidgets.cxx
@@ -232,8 +232,8 @@ UInt32 AquaSalGraphics::getState(ControlState nState)
// there are non key windows which are children of key windows, e.g. autofilter configuration dialog or sidebar dropdown dialogs.
// To handle these windows correctly, parent frame's key window state is considered here additionally.
- const bool bDrawActive = mpFrame == nullptr || [mpFrame->getNSWindow() isKeyWindow]
- || mpFrame->mpParent == nullptr || [mpFrame->mpParent->getNSWindow() isKeyWindow];
+ const bool bDrawActive = maShared.mpFrame == nullptr || [maShared.mpFrame->getNSWindow() isKeyWindow]
+ || maShared.mpFrame->mpParent == nullptr || [maShared.mpFrame->mpParent->getNSWindow() isKeyWindow];
if (!(nState & ControlState::ENABLED) || !bDrawActive)
{
return kThemeStateInactive;
@@ -245,7 +245,7 @@ UInt32 AquaSalGraphics::getState(ControlState nState)
UInt32 AquaSalGraphics::getTrackState(ControlState nState)
{
- const bool bDrawActive = mpFrame == nullptr || [mpFrame->getNSWindow() isKeyWindow];
+ const bool bDrawActive = maShared.mpFrame == nullptr || [maShared.mpFrame->getNSWindow() isKeyWindow];
if (!(nState & ControlState::ENABLED) || !bDrawActive)
return kThemeTrackInactive;
return kThemeTrackActive;
@@ -260,9 +260,9 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
const Color&)
{
bool bOK = false;
- if (!CheckContext())
+ if (!maShared.checkContext())
return false;
- maContextHolder.saveState();
+ maShared.maContextHolder.saveState();
tools::Rectangle buttonRect = rControlRegion;
HIRect rc = ImplGetHIRectFromRectangle(buttonRect);
switch (nType)
@@ -274,15 +274,15 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aMenuItemDrawInfo.version = 0;
aMenuItemDrawInfo.state = kThemeMenuActive;
aMenuItemDrawInfo.itemType = kThemeMenuItemHierBackground;
- HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
#else
if (rControlRegion.Top() == 0 && nPart == ControlPart::DrawBackgroundHorz)
{
- const bool bDrawActive = mpFrame == nullptr || [mpFrame->getNSWindow() isKeyWindow];
+ const bool bDrawActive = maShared.mpFrame == nullptr || [maShared.mpFrame->getNSWindow() isKeyWindow];
CGFloat unifiedHeight = rControlRegion.GetHeight();
CGRect drawRect = CGRectMake(rControlRegion.Left(), rControlRegion.Top(),
rControlRegion.GetWidth(), rControlRegion.GetHeight());
- CUIDraw([NSWindow coreUIRenderer], drawRect, maContextHolder.get(),
+ CUIDraw([NSWindow coreUIRenderer], drawRect, maShared.maContextHolder.get(),
reinterpret_cast<CFDictionaryRef>([NSDictionary dictionaryWithObjectsAndKeys:
@"kCUIWidgetWindowFrame",
@"widget",
@@ -305,7 +305,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aMenuItemDrawInfo.version = 0;
aMenuItemDrawInfo.state = kThemeMenuActive;
aMenuItemDrawInfo.itemType = kThemeMenuItemHierBackground;
- HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
}
#endif
bOK = true;
@@ -322,8 +322,8 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.size.width += 2;
rc.size.height += 2;
- HIThemeApplyBackground( &rc, &aThemeBackgroundInfo, maContextHolder.get(), kHIThemeOrientationNormal);
- CGContextFillRect(maContextHolder.get(), rc);
+ HIThemeApplyBackground( &rc, &aThemeBackgroundInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ CGContextFillRect(maShared.maContextHolder.get(), rc);
bOK = true;
}
break;
@@ -335,8 +335,8 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aThemeBackgroundInfo.kind = kThemeBrushAlertBackgroundActive;
rc.size.width += 2;
rc.size.height += 2;
- HIThemeApplyBackground(&rc, &aThemeBackgroundInfo, maContextHolder.get(), kHIThemeOrientationNormal);
- CGContextFillRect(maContextHolder.get(), rc);
+ HIThemeApplyBackground(&rc, &aThemeBackgroundInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ CGContextFillRect(maShared.maContextHolder.get(), rc);
bOK = true;
}
break;
@@ -369,11 +369,11 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
// repaints the background of the pull down menu
- HIThemeDrawMenuBackground(&rc, &aMenuInfo,maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawMenuBackground(&rc, &aMenuInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
// repaints the item either blue (selected) and/or grey (active only)
- HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, maContextHolder.get(), kHIThemeOrientationNormal, &rc);
+ HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, &rc);
bOK = true;
}
else if (nPart == ControlPart::MenuItemCheckMark || nPart == ControlPart::MenuItemRadioMark)
@@ -397,7 +397,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
if (nState & ControlState::SELECTED) aTextInfo.state = kThemeStatePressed;
UniChar mark=(nPart == ControlPart::MenuItemCheckMark) ? kCheckUnicode: kBulletUnicode;
CFStringRef cfString = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, &mark, 1, kCFAllocatorNull);
- HIThemeDrawTextBox(cfString, &rc, &aTextInfo, maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTextBox(cfString, &rc, &aTextInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
if (cfString)
CFRelease(cfString);
bOK = true;
@@ -449,7 +449,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aPushInfo.adornment = (nState & ControlState::DEFAULT) ? kThemeAdornmentDefault : kThemeAdornmentNone;
if (nState & ControlState::FOCUSED)
aPushInfo.adornment |= kThemeAdornmentFocus;
- HIThemeDrawButton(&rc, &aPushInfo, maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aPushInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
bOK = true;
}
break;
@@ -485,7 +485,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.size.height = RADIO_BUTTON_SMALL_SIZE;
rc.origin.x += FOCUS_RING_WIDTH;
rc.origin.y += FOCUS_RING_WIDTH;
- HIThemeDrawButton(&rc, &aInfo, maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
bOK = true;
}
break;
@@ -511,7 +511,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
default:
break;
}
- HIThemeDrawButton(&rc, &aInfo, maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
bOK = true;
}
break;
@@ -538,7 +538,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aTrackInfo.enableState = kThemeTrackActive;
aTrackInfo.filler1 = 0;
aTrackInfo.trackInfo.progress.phase = static_cast<long long>(CFAbsoluteTimeGetCurrent() * 10.0);
- HIThemeDrawTrack(&aTrackInfo, nullptr, maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTrack(&aTrackInfo, nullptr, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
bOK = true;
}
break;
@@ -562,7 +562,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aSlideInfo.thumbDir = kThemeThumbUpward;
aSlideInfo.pressState = 0;
aTrackDraw.trackInfo.slider = aSlideInfo;
- HIThemeDrawTrack(&aTrackDraw, nullptr, maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTrack(&aTrackDraw, nullptr, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
bOK = true;
}
}
@@ -597,7 +597,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
if (pScrollbarVal->mnThumbState & ControlState::PRESSED)
aScrollInfo.pressState = kThemeThumbPressed;
aTrackDraw.trackInfo.scrollbar = aScrollInfo;
- HIThemeDrawTrack(&aTrackDraw, nullptr, maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTrack(&aTrackDraw, nullptr, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
bOK = true;
}
}
@@ -617,7 +617,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.origin.y -= TAB_HEIGHT / 2;
rc.size.height += TAB_HEIGHT / 2;
rc.size.width -= 2;
- HIThemeDrawTabPane(&rc, &aTabPaneDrawInfo, maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTabPane(&rc, &aTabPaneDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
bOK = true;
}
break;
@@ -661,7 +661,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
else if (aTabItemDrawInfo.position == kHIThemeTabPositionLast)
aTabItemDrawInfo.position = kHIThemeTabPositionFirst;
}
- HIThemeDrawTab(&rc, &aTabItemDrawInfo, maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawTab(&rc, &aTabItemDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
bOK=true;
}
break;
@@ -683,10 +683,10 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
// fill a white background, because HIThemeDrawFrame only draws the border
- CGContextFillRect(maContextHolder.get(), CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height));
- HIThemeDrawFrame(&rc, &aTextDrawInfo, maContextHolder.get(), kHIThemeOrientationNormal);
+ CGContextFillRect(maShared.maContextHolder.get(), CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height));
+ HIThemeDrawFrame(&rc, &aTextDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
if (nState & ControlState::FOCUSED)
- HIThemeDrawFocusRect(&rc, true, maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawFocusRect(&rc, true, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
bOK = true;
}
break;
@@ -705,7 +705,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.size.height = COMBOBOX_HEIGHT;
rc.origin.x += FOCUS_RING_WIDTH;
rc.origin.y += FOCUS_RING_WIDTH;
- HIThemeDrawButton(&rc, &aComboInfo, maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aComboInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
bOK = true;
}
break;
@@ -726,7 +726,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.size.height = LISTBOX_HEIGHT;
rc.origin.x += FOCUS_RING_WIDTH;
rc.origin.y += FOCUS_RING_WIDTH;
- HIThemeDrawButton(&rc, &aListInfo, maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aListInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
bOK = true;
break;
case ControlPart::ListboxWindow:
@@ -735,7 +735,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aTextDrawInfo.kind = kHIThemeFrameListBox;
aTextDrawInfo.state = kThemeStateActive;
aTextDrawInfo.isFocused = false;
- HIThemeDrawFrame(&rc, &aTextDrawInfo, maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawFrame(&rc, &aTextDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
bOK = true;
break;
default:
@@ -760,10 +760,10 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
// fill a white background, because HIThemeDrawFrame only draws the border
- CGContextFillRect(maContextHolder.get(), CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height));
- HIThemeDrawFrame(&rc, &aTextDrawInfo, maContextHolder.get(), kHIThemeOrientationNormal);
+ CGContextFillRect(maShared.maContextHolder.get(), CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height));
+ HIThemeDrawFrame(&rc, &aTextDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
if (nState & ControlState::FOCUSED)
- HIThemeDrawFocusRect(&rc, true, maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawFocusRect(&rc, true, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
// buttons
@@ -808,7 +808,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.origin.y -= 1;
rc.size.width = SPIN_BUTTON_WIDTH;
rc.size.height = SPIN_LOWER_BUTTON_HEIGHT + SPIN_LOWER_BUTTON_HEIGHT;
- HIThemeDrawButton(&rc, &aSpinInfo, maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aSpinInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
}
bOK = true;
}
@@ -824,14 +824,14 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
// strange effects start to happen when HIThemeDrawFrame meets the border of the window.
// These can be avoided by clipping to the boundary of the frame (see issue 84756)
- if (rc.origin.y + rc.size.height >= mpFrame->maGeometry.nHeight - 3)
+ if (rc.origin.y + rc.size.height >= maShared.mpFrame->maGeometry.nHeight - 3)
{
CGMutablePathRef rPath = CGPathCreateMutable();
CGPathAddRect(rPath, nullptr,
- CGRectMake(0, 0, mpFrame->maGeometry.nWidth - 1, mpFrame->maGeometry.nHeight - 1));
- CGContextBeginPath(maContextHolder.get());
- CGContextAddPath(maContextHolder.get(), rPath);
- CGContextClip(maContextHolder.get());
+ CGRectMake(0, 0, maShared.mpFrame->maGeometry.nWidth - 1, maShared.mpFrame->maGeometry.nHeight - 1));
+ CGContextBeginPath(maShared.maContextHolder.get());
+ CGContextAddPath(maShared.maContextHolder.get(), rPath);
+ CGContextClip(maShared.maContextHolder.get());
CGPathRelease(rPath);
}
HIThemeFrameDrawInfo aTextDrawInfo;
@@ -839,7 +839,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aTextDrawInfo.kind = kHIThemeFrameListBox;
aTextDrawInfo.state = kThemeStateActive;
aTextDrawInfo.isFocused = false;
- HIThemeDrawFrame(&rc, &aTextDrawInfo, maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawFrame(&rc, &aTextDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
bOK = true;
}
}
@@ -854,7 +854,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
default:
break;
}
- maContextHolder.restoreState();
+ maShared.maContextHolder.restoreState();
// in most cases invalidating the whole control region instead of just the unclipped part of it is sufficient (and probably
// faster). However for the window background we should not unnecessarily enlarge the really changed rectangle since the
@@ -864,15 +864,15 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
if (nType == ControlType::WindowBackground)
{
CGRect aRect = {{0, 0}, {0, 0}};
- if (mxClipPath)
- aRect = CGPathGetBoundingBox(mxClipPath);
+ if (maShared.mxClipPath)
+ aRect = CGPathGetBoundingBox(maShared.mxClipPath);
if (aRect.size.width != 0 && aRect.size.height != 0)
buttonRect.Intersection(tools::Rectangle(Point(static_cast<tools::Long>(aRect.origin.x),
static_cast<tools::Long>(aRect.origin.y)),
Size(static_cast<tools::Long>(aRect.size.width),
static_cast<tools::Long>(aRect.size.height))));
}
- RefreshRect(buttonRect.Left(), buttonRect.Top(), buttonRect.GetWidth(), buttonRect.GetHeight());
+ maShared.refreshRect(buttonRect.Left(), buttonRect.Top(), buttonRect.GetWidth(), buttonRect.GetHeight());
return bOK;
}
diff --git a/vcl/quartz/AquaGraphicsBackend.cxx b/vcl/quartz/AquaGraphicsBackend.cxx
new file mode 100644
index 000000000000..0aa6042f7eb4
--- /dev/null
+++ b/vcl/quartz/AquaGraphicsBackend.cxx
@@ -0,0 +1,1355 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <cassert>
+#include <cstring>
+#include <numeric>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <osl/endian.h>
+#include <osl/file.hxx>
+#include <sal/types.h>
+#include <tools/long.hxx>
+#include <vcl/sysdata.hxx>
+
+#include <fontsubset.hxx>
+#include <quartz/salbmp.h>
+#ifdef MACOSX
+#include <quartz/salgdi.h>
+#endif
+#include <quartz/utils.h>
+#ifdef IOS
+#include "saldatabasic.hxx"
+#endif
+#include <sft.hxx>
+
+using namespace vcl;
+
+namespace
+{
+const basegfx::B2DPoint aHalfPointOfs(0.5, 0.5);
+
+static void AddPolygonToPath(CGMutablePathRef xPath, const basegfx::B2DPolygon& rPolygon,
+ bool bClosePath, bool bPixelSnap, bool bLineDraw)
+{
+ // short circuit if there is nothing to do
+ const int nPointCount = rPolygon.count();
+ if (nPointCount <= 0)
+ {
+ return;
+ }
+
+ const bool bHasCurves = rPolygon.areControlPointsUsed();
+ for (int nPointIdx = 0, nPrevIdx = 0;; nPrevIdx = nPointIdx++)
+ {
+ int nClosedIdx = nPointIdx;
+ if (nPointIdx >= nPointCount)
+ {
+ // prepare to close last curve segment if needed
+ if (bClosePath && (nPointIdx == nPointCount))
+ {
+ nClosedIdx = 0;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ basegfx::B2DPoint aPoint = rPolygon.getB2DPoint(nClosedIdx);
+
+ if (bPixelSnap)
+ {
+ // snap device coordinates to full pixels
+ aPoint.setX(basegfx::fround(aPoint.getX()));
+ aPoint.setY(basegfx::fround(aPoint.getY()));
+ }
+
+ if (bLineDraw)
+ {
+ aPoint += aHalfPointOfs;
+ }
+ if (!nPointIdx)
+ {
+ // first point => just move there
+ CGPathMoveToPoint(xPath, nullptr, aPoint.getX(), aPoint.getY());
+ continue;
+ }
+
+ bool bPendingCurve = false;
+ if (bHasCurves)
+ {
+ bPendingCurve = rPolygon.isNextControlPointUsed(nPrevIdx);
+ bPendingCurve |= rPolygon.isPrevControlPointUsed(nClosedIdx);
+ }
+
+ if (!bPendingCurve) // line segment
+ {
+ CGPathAddLineToPoint(xPath, nullptr, aPoint.getX(), aPoint.getY());
+ }
+ else // cubic bezier segment
+ {
+ basegfx::B2DPoint aCP1 = rPolygon.getNextControlPoint(nPrevIdx);
+ basegfx::B2DPoint aCP2 = rPolygon.getPrevControlPoint(nClosedIdx);
+ if (bLineDraw)
+ {
+ aCP1 += aHalfPointOfs;
+ aCP2 += aHalfPointOfs;
+ }
+ CGPathAddCurveToPoint(xPath, nullptr, aCP1.getX(), aCP1.getY(), aCP2.getX(),
+ aCP2.getY(), aPoint.getX(), aPoint.getY());
+ }
+ }
+
+ if (bClosePath)
+ {
+ CGPathCloseSubpath(xPath);
+ }
+}
+
+static void alignLinePoint(const Point* i_pIn, float& o_fX, float& o_fY)
+{
+ o_fX = static_cast<float>(i_pIn->getX()) + 0.5;
+ o_fY = static_cast<float>(i_pIn->getY()) + 0.5;
+}
+
+static void getBoundRect(sal_uInt32 nPoints, const Point* pPtAry, tools::Long& rX, tools::Long& rY,
+ tools::Long& rWidth, tools::Long& rHeight)
+{
+ tools::Long nX1 = pPtAry->getX();
+ tools::Long nX2 = nX1;
+ tools::Long nY1 = pPtAry->getY();
+ tools::Long nY2 = nY1;
+
+ for (sal_uInt32 n = 1; n < nPoints; n++)
+ {
+ if (pPtAry[n].getX() < nX1)
+ {
+ nX1 = pPtAry[n].getX();
+ }
+ else if (pPtAry[n].getX() > nX2)
+ {
+ nX2 = pPtAry[n].getX();
+ }
+ if (pPtAry[n].getY() < nY1)
+ {
+ nY1 = pPtAry[n].getY();
+ }
+ else if (pPtAry[n].getY() > nY2)
+ {
+ nY2 = pPtAry[n].getY();
+ }
+ }
+ rX = nX1;
+ rY = nY1;
+ rWidth = nX2 - nX1 + 1;
+ rHeight = nY2 - nY1 + 1;
+}
+
+static Color ImplGetROPColor(SalROPColor nROPColor)
+{
+ Color nColor;
+ if (nROPColor == SalROPColor::N0)
+ {
+ nColor = Color(0, 0, 0);
+ }
+ else
+ {
+ nColor = Color(255, 255, 255);
+ }
+ return nColor;
+}
+
+static void drawPattern50(void*, CGContextRef rContext)
+{
+ static const CGRect aRects[2] = { { { 0, 0 }, { 2, 2 } }, { { 2, 2 }, { 2, 2 } } };
+ CGContextAddRects(rContext, aRects, 2);
+ CGContextFillPath(rContext);
+}
+}
+
+AquaGraphicsBackend::AquaGraphicsBackend(AquaSharedAttributes& rShared)
+ : mrShared(rShared)
+{
+}
+
+AquaGraphicsBackend::~AquaGraphicsBackend() {}
+
+void AquaGraphicsBackend::Init() {}
+void AquaGraphicsBackend::freeResources() {}
+
+bool AquaGraphicsBackend::setClipRegion(vcl::Region const& rRegion)
+{
+ // release old clip path
+ mrShared.unsetClipPath();
+ mrShared.mxClipPath = CGPathCreateMutable();
+
+ // set current path, either as polypolgon or sequence of rectangles
+ RectangleVector aRectangles;
+ rRegion.GetRegionRectangles(aRectangles);
+
+ for (const auto& rRect : aRectangles)
+ {
+ const tools::Long nW(rRect.Right() - rRect.Left() + 1); // uses +1 logic in original
+
+ if (nW)
+ {
+ const tools::Long nH(rRect.Bottom() - rRect.Top() + 1); // uses +1 logic in original
+
+ if (nH)
+ {
+ const CGRect aRect = CGRectMake(rRect.Left(), rRect.Top(), nW, nH);
+ CGPathAddRect(mrShared.mxClipPath, nullptr, aRect);
+ }
+ }
+ }
+ // set the current path as clip region
+ if (mrShared.checkContext())
+ mrShared.setState();
+
+ return true;
+}
+
+void AquaGraphicsBackend::ResetClipRegion()
+{
+ // release old path and indicate no clipping
+ mrShared.unsetClipPath();
+
+ if (mrShared.checkContext())
+ {
+ mrShared.setState();
+ }
+}
+
+sal_uInt16 AquaGraphicsBackend::GetBitCount() const
+{
+ sal_uInt16 nBits = mrShared.mnBitmapDepth ? mrShared.mnBitmapDepth : 32; //24;
+ return nBits;
+}
+
+tools::Long AquaGraphicsBackend::GetGraphicsWidth() const
+{
+ tools::Long width = 0;
+ if (mrShared.maContextHolder.isSet()
+ && (
+#ifndef IOS
+ mrShared.mbWindow ||
+#endif
+ mrShared.mbVirDev))
+ {
+ width = mrShared.mnWidth;
+ }
+
+#ifndef IOS
+ if (width == 0)
+ {
+ if (mrShared.mbWindow && mrShared.mpFrame)
+ {
+ width = mrShared.mpFrame->maGeometry.nWidth;
+ }
+ }
+#endif
+ return width;
+}
+
+void AquaGraphicsBackend::SetLineColor()
+{
+ mrShared.maLineColor.SetAlpha(0.0); // transparent
+ if (mrShared.checkContext())
+ {
+ CGContextSetRGBStrokeColor(mrShared.maContextHolder.get(), mrShared.maLineColor.GetRed(),
+ mrShared.maLineColor.GetGreen(), mrShared.maLineColor.GetBlue(),
+ mrShared.maLineColor.GetAlpha());
+ }
+}
+
+void AquaGraphicsBackend::SetLineColor(Color nColor)
+{
+ mrShared.maLineColor = RGBAColor(nColor);
+ if (mrShared.checkContext())
+ {
+ CGContextSetRGBStrokeColor(mrShared.maContextHolder.get(), mrShared.maLineColor.GetRed(),
+ mrShared.maLineColor.GetGreen(), mrShared.maLineColor.GetBlue(),
+ mrShared.maLineColor.GetAlpha());
+ }
+}
+
+void AquaGraphicsBackend::SetFillColor()
+{
+ mrShared.maFillColor.SetAlpha(0.0); // transparent
+ if (mrShared.checkContext())
+ {
+ CGContextSetRGBFillColor(mrShared.maContextHolder.get(), mrShared.maFillColor.GetRed(),
+ mrShared.maFillColor.GetGreen(), mrShared.maFillColor.GetBlue(),
+ mrShared.maFillColor.GetAlpha());
+ }
+}
+
+void AquaGraphicsBackend::SetFillColor(Color nColor)
+{
+ mrShared.maFillColor = RGBAColor(nColor);
+ if (mrShared.checkContext())
+ {
+ CGContextSetRGBFillColor(mrShared.maContextHolder.get(), mrShared.maFillColor.GetRed(),
+ mrShared.maFillColor.GetGreen(), mrShared.maFillColor.GetBlue(),
+ mrShared.maFillColor.GetAlpha());
+ }
+}
+
+void AquaGraphicsBackend::SetXORMode(bool bSet, bool bInvertOnly)
+{
+ // return early if XOR mode remains unchanged
+ if (mrShared.mbPrinter)
+ {
+ return;
+ }
+ if (!bSet && mrShared.mnXorMode == 2)
+ {
+ CGContextSetBlendMode(mrShared.maContextHolder.get(), kCGBlendModeNormal);
+ mrShared.mnXorMode = 0;
+ return;
+ }
+ else if (bSet && bInvertOnly && mrShared.mnXorMode == 0)
+ {
+ CGContextSetBlendMode(mrShared.maContextHolder.get(), kCGBlendModeDifference);
+ mrShared.mnXorMode = 2;
+ return;
+ }
+
+ if (!mrShared.mpXorEmulation && !bSet)
+ {
+ return;
+ }
+ if (mrShared.mpXorEmulation && bSet == mrShared.mpXorEmulation->IsEnabled())
+ {
+ return;
+ }
+ if (!mrShared.checkContext())
+ {
+ return;
+ }
+ // prepare XOR emulation
+ if (!mrShared.mpXorEmulation)
+ {
+ mrShared.mpXorEmulation = std::make_unique<XorEmulation>();
+ mrShared.mpXorEmulation->SetTarget(mrShared.mnWidth, mrShared.mnHeight,
+ mrShared.mnBitmapDepth, mrShared.maContextHolder.get(),
+ mrShared.maLayer.get());
+ }
+
+ // change the XOR mode
+ if (bSet)
+ {
+ mrShared.mpXorEmulation->Enable();
+ mrShared.maContextHolder.set(mrShared.mpXorEmulation->GetMaskContext());
+ mrShared.mnXorMode = 1;
+ }
+ else
+ {
+ mrShared.mpXorEmulation->UpdateTarget();
+ mrShared.mpXorEmulation->Disable();
+ mrShared.maContextHolder.set(mrShared.mpXorEmulation->GetTargetContext());
+ mrShared.mnXorMode = 0;
+ }
+}
+
+void AquaGraphicsBackend::SetROPFillColor(SalROPColor nROPColor)
+{
+ if (!mrShared.mbPrinter)
+ {
+ SetFillColor(ImplGetROPColor(nROPColor));
+ }
+}
+
+void AquaGraphicsBackend::SetROPLineColor(SalROPColor nROPColor)
+{
+ if (!mrShared.mbPrinter)
+ {
+ SetLineColor(ImplGetROPColor(nROPColor));
+ }
+}
+
+void AquaGraphicsBackend::drawPixelImpl(tools::Long nX, tools::Long nY, const RGBAColor& rColor)
+{
+ if (!mrShared.checkContext())
+ return;
+
+ // overwrite the fill color
+ CGContextSetFillColor(mrShared.maContextHolder.get(), rColor.AsArray());
+ // draw 1x1 rect, there is no pixel drawing in Quartz
+ const CGRect aDstRect = CGRectMake(nX, nY, 1, 1);
+ CGContextFillRect(mrShared.maContextHolder.get(), aDstRect);
+
+ refreshRect(aDstRect);
+
+ // reset the fill color
+ CGContextSetFillColor(mrShared.maContextHolder.get(), mrShared.maFillColor.AsArray());
+}
+
+void AquaGraphicsBackend::drawPixel(tools::Long nX, tools::Long nY)
+{
+ // draw pixel with current line color
+ drawPixelImpl(nX, nY, mrShared.maLineColor);
+}
+
+void AquaGraphicsBackend::drawPixel(tools::Long nX, tools::Long nY, Color nColor)
+{
+ const RGBAColor aPixelColor(nColor);
+ drawPixelImpl(nX, nY, aPixelColor);
+}
+
+void AquaGraphicsBackend::drawLine(tools::Long nX1, tools::Long nY1, tools::Long nX2,
+ tools::Long nY2)
+{
+ if (nX1 == nX2 && nY1 == nY2)
+ {
+ // #i109453# platform independent code expects at least one pixel to be drawn
+ drawPixel(nX1, nY1);
+ return;
+ }
+
+ if (!mrShared.checkContext())
+ return;
+
+ CGContextBeginPath(mrShared.maContextHolder.get());
+ CGContextMoveToPoint(mrShared.maContextHolder.get(), float(nX1) + 0.5, float(nY1) + 0.5);
+ CGContextAddLineToPoint(mrShared.maContextHolder.get(), float(nX2) + 0.5, float(nY2) + 0.5);
+ CGContextDrawPath(mrShared.maContextHolder.get(), kCGPathStroke);
+
+ tools::Rectangle aRefreshRect(nX1, nY1, nX2, nY2);
+ (void)aRefreshRect;
+ // Is a call to RefreshRect( aRefreshRect ) missing here?
+}
+
+void AquaGraphicsBackend::drawRect(tools::Long nX, tools::Long nY, tools::Long nWidth,
+ tools::Long nHeight)
+{
+ if (!mrShared.checkContext())
+ return;
+
+ CGRect aRect = CGRectMake(nX, nY, nWidth, nHeight);
+ if (mrShared.isPenVisible())
+ {
+ aRect.origin.x += 0.5;
+ aRect.origin.y += 0.5;
+ aRect.size.width -= 1;
+ aRect.size.height -= 1;
+ }
+
+ if (mrShared.isBrushVisible())
+ {
+ CGContextFillRect(mrShared.maContextHolder.get(), aRect);
+ }
+ if (mrShared.isPenVisible())
+ {
+ CGContextStrokeRect(mrShared.maContextHolder.get(), aRect);
+ }
+ mrShared.refreshRect(nX, nY, nWidth, nHeight);
+}
+
+void AquaGraphicsBackend::drawPolyLine(sal_uInt32 nPoints, const Point* pPointArray)
+{
+ if (nPoints < 1)
+ return;
+
+ if (!mrShared.checkContext())
+ return;
+
+ tools::Long nX = 0, nY = 0, nWidth = 0, nHeight = 0;
+ getBoundRect(nPoints, pPointArray, nX, nY, nWidth, nHeight);
+
+ float fX, fY;
+ CGContextBeginPath(mrShared.maContextHolder.get());
+ alignLinePoint(pPointArray, fX, fY);
+ CGContextMoveToPoint(mrShared.maContextHolder.get(), fX, fY);
+ pPointArray++;
+
+ for (sal_uInt32 nPoint = 1; nPoint < nPoints; nPoint++, pPointArray++)
+ {
+ alignLinePoint(pPointArray, fX, fY);
+ CGContextAddLineToPoint(mrShared.maContextHolder.get(), fX, fY);
+ }
+ CGContextStrokePath(mrShared.maContextHolder.get());
+
+ mrShared.refreshRect(nX, nY, nWidth, nHeight);
+}
+
+void AquaGraphicsBackend::drawPolygon(sal_uInt32 nPoints, const Point* pPointArray)
+{
+ if (nPoints <= 1)
+ return;
+
+ if (!mrShared.checkContext())
+ return;
+
+ tools::Long nX = 0, nY = 0, nWidth = 0, nHeight = 0;
+ getBoundRect(nPoints, pPointArray, nX, nY, nWidth, nHeight);
+
+ CGPathDrawingMode eMode;
+ if (mrShared.isBrushVisible() && mrShared.isPenVisible())
+ {
+ eMode = kCGPathEOFillStroke;
+ }
+ else if (mrShared.isPenVisible())
+ {
+ eMode = kCGPathStroke;
+ }
+ else if (mrShared.isBrushVisible())
+ {
+ eMode = kCGPathEOFill;
+ }
+ else
+ {
+ SAL_WARN("vcl.quartz", "Neither pen nor brush visible");
+ return;
+ }
+
+ CGContextBeginPath(mrShared.maContextHolder.get());
+
+ if (mrShared.isPenVisible())
+ {
+ float fX, fY;
+ alignLinePoint(pPointArray, fX, fY);
+ CGContextMoveToPoint(mrShared.maContextHolder.get(), fX, fY);
+ pPointArray++;
+ for (sal_uInt32 nPoint = 1; nPoint < nPoints; nPoint++, pPointArray++)
+ {
+ alignLinePoint(pPointArray, fX, fY);
+ CGContextAddLineToPoint(mrShared.maContextHolder.get(), fX, fY);
+ }
+ }
+ else
+ {
+ CGContextMoveToPoint(mrShared.maContextHolder.get(), pPointArray->getX(),
+ pPointArray->getY());
+ pPointArray++;
+ for (sal_uInt32 nPoint = 1; nPoint < nPoints; nPoint++, pPointArray++)
+ {
+ CGContextAddLineToPoint(mrShared.maContextHolder.get(), pPointArray->getX(),
+ pPointArray->getY());
+ }
+ }
+
+ CGContextClosePath(mrShared.maContextHolder.get());
+ CGContextDrawPath(mrShared.maContextHolder.get(), eMode);
+
+ mrShared.refreshRect(nX, nY, nWidth, nHeight);
+}
+
+void AquaGraphicsBackend::drawPolyPolygon(sal_uInt32 nPolyCount, const sal_uInt32* pPoints,
+ const Point** ppPtAry)
+{
+ if (nPolyCount <= 0)
+ return;
+
+ if (!mrShared.checkContext())
+ return;
+
+ // find bound rect
+ tools::Long leftX = 0, topY = 0, maxWidth = 0, maxHeight = 0;
+
+ getBoundRect(pPoints[0], ppPtAry[0], leftX, topY, maxWidth, maxHeight);
+
+ for (sal_uInt32 n = 1; n < nPolyCount; n++)
+ {
+ tools::Long nX = leftX, nY = topY, nW = maxWidth, nH = maxHeight;
+ getBoundRect(pPoints[n], ppPtAry[n], nX, nY, nW, nH);
+ if (nX < leftX)
+ {
+ maxWidth += leftX - nX;
+ leftX = nX;
+ }
+ if (nY < topY)
+ {
+ maxHeight += topY - nY;
+ topY = nY;
+ }
+ if (nX + nW > leftX + maxWidth)
+ {
+ maxWidth = nX + nW - leftX;
+ }
+ if (nY + nH > topY + maxHeight)
+ {
+ maxHeight = nY + nH - topY;
+ }
+ }
+
+ // prepare drawing mode
+ CGPathDrawingMode eMode;
+ if (mrShared.isBrushVisible() && mrShared.isPenVisible())
+ {
+ eMode = kCGPathEOFillStroke;
+ }
+ else if (mrShared.isPenVisible())
+ {
+ eMode = kCGPathStroke;
+ }
+ else if (mrShared.isBrushVisible())
+ {
+ eMode = kCGPathEOFill;
+ }
+ else
+ {
+ SAL_WARN("vcl.quartz", "Neither pen nor brush visible");
+ return;
+ }
+
+ // convert to CGPath
+ CGContextBeginPath(mrShared.maContextHolder.get());
+ if (mrShared.isPenVisible())
+ {
+ for (sal_uInt32 nPoly = 0; nPoly < nPolyCount; nPoly++)
+ {
+ const sal_uInt32 nPoints = pPoints[nPoly];
+ if (nPoints > 1)
+ {
+ const Point* pPtAry = ppPtAry[nPoly];
+ float fX, fY;
+
+ alignLinePoint(pPtAry, fX, fY);
+ CGContextMoveToPoint(mrShared.maContextHolder.get(), fX, fY);
+ pPtAry++;
+
+ for (sal_uInt32 nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++)
+ {
+ alignLinePoint(pPtAry, fX, fY);
+ CGContextAddLineToPoint(mrShared.maContextHolder.get(), fX, fY);
+ }
+ CGContextClosePath(mrShared.maContextHolder.get());
+ }
+ }
+ }
+ else
+ {
+ for (sal_uInt32 nPoly = 0; nPoly < nPolyCount; nPoly++)
+ {
+ const sal_uInt32 nPoints = pPoints[nPoly];
+ if (nPoints > 1)
+ {
+ const Point* pPtAry = ppPtAry[nPoly];
+ CGContextMoveToPoint(mrShared.maContextHolder.get(), pPtAry->getX(),
+ pPtAry->getY());
+ pPtAry++;
+ for (sal_uInt32 nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++)
+ {
+ CGContextAddLineToPoint(mrShared.maContextHolder.get(), pPtAry->getX(),
+ pPtAry->getY());
+ }
+ CGContextClosePath(mrShared.maContextHolder.get());
+ }
+ }
+ }
+
+ CGContextDrawPath(mrShared.maContextHolder.get(), eMode);
+
+ mrShared.refreshRect(leftX, topY, maxWidth, maxHeight);
+}
+
+bool AquaGraphicsBackend::drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fTransparency)
+{
+#ifdef IOS
+ if (!mrShared.maContextHolder.isSet())
+ return true;
+#endif
+
+ // short circuit if there is nothing to do
+ if (rPolyPolygon.count() == 0)
+ return true;
+
+ // ignore invisible polygons
+ if ((fTransparency >= 1.0) || (fTransparency < 0))
+ return true;
+
+ // Fallback: Transform to DeviceCoordinates
+ basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
+ aPolyPolygon.transform(rObjectToDevice);
+
+ // setup poly-polygon path
+ CGMutablePathRef xPath = CGPathCreateMutable();
+ // tdf#120252 Use the correct, already transformed PolyPolygon (as long as
+ // the transformation is not used here...)
+ for (auto const& rPolygon : aPolyPolygon)
+ {
+ AddPolygonToPath(xPath, rPolygon, true, !getAntiAlias(), mrShared.isPenVisible());
+ }
+
+ const CGRect aRefreshRect = CGPathGetBoundingBox(xPath);
+ // #i97317# workaround for Quartz having problems with drawing small polygons
+ if (aRefreshRect.size.width > 0.125 || aRefreshRect.size.height > 0.125)
+ {
+ // prepare drawing mode
+ CGPathDrawingMode eMode;
+ if (mrShared.isBrushVisible() && mrShared.isPenVisible())
+ {
+ eMode = kCGPathEOFillStroke;
+ }
+ else if (mrShared.isPenVisible())
+ {
+ eMode = kCGPathStroke;
+ }
+ else if (mrShared.isBrushVisible())
+ {
+ eMode = kCGPathEOFill;
+ }
+ else
+ {
+ SAL_WARN("vcl.quartz", "Neither pen nor brush visible");
+ CGPathRelease(xPath);
+ return true;
+ }
+
+ // use the path to prepare the graphics context
+ mrShared.maContextHolder.saveState();
+ CGContextBeginPath(mrShared.maContextHolder.get());
+ CGContextAddPath(mrShared.maContextHolder.get(), xPath);
+
+ // draw path with antialiased polygon
+ CGContextSetShouldAntialias(mrShared.maContextHolder.get(), getAntiAlias());
+ CGContextSetAlpha(mrShared.maContextHolder.get(), 1.0 - fTransparency);
+ CGContextDrawPath(mrShared.maContextHolder.get(), eMode);
+ mrShared.maContextHolder.restoreState();
+
+ // mark modified rectangle as updated
+ refreshRect(aRefreshRect);
+ }
+
+ CGPathRelease(xPath);
+
+ return true;
+}
+
+bool AquaGraphicsBackend::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice,
+ const basegfx::B2DPolygon& rPolyLine, double fTransparency,
+ double fLineWidth,
+ const std::vector<double>* pStroke, // MM01
+ basegfx::B2DLineJoin eLineJoin,
+ css::drawing::LineCap eLineCap, double fMiterMinimumAngle,
+ bool bPixelSnapHairline)
+{
+ // MM01 check done for simple reasons
+ if (!rPolyLine.count() || fTransparency < 0.0 || fTransparency > 1.0)
+ {
+ return true;
+ }
+
+#ifdef IOS
+ if (!mrShared.checkContext())
+ return false;
+#endif
+
+ // tdf#124848 get correct LineWidth in discrete coordinates,
+ if (fLineWidth == 0) // hairline
+ fLineWidth = 1.0;
+ else // Adjust line width for object-to-device scale.
+ fLineWidth = (rObjectToDevice * basegfx::B2DVector(fLineWidth, 0)).getLength();
+
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list