summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Mohrhard <markus.mohrhard@collabora.co.uk>2014-11-04 04:29:13 +0100
committerMarkus Mohrhard <markus.mohrhard@collabora.co.uk>2014-11-04 04:33:02 +0100
commit4af8f41df1c85fe0ec84b6a2c8f39b741aa5f09f (patch)
treedb43e7c7e5ff9d5dd979bfa50f40fc6a99b8b14f
parentade03f86a390889d3888c7c1c603f5b415446d76 (diff)
extract cairo rendering and abstract platform bitsfeature/opengl-vcl-text
The text rendering is now abstracted into the TextRender abstract class. Additionally we have now an abstracted cairo rendering class CairoTextRender which is a subclass of the TextRender class. The CairoTextRender class is still platform independent and needs to be subclassed to implement the few platform dependent methods. You can reuse the cairo based text rendering now by subclassing CairoTextRender for the platform that you need. Change-Id: I8b07e3fe646a81563d308971d30e14a00fd921ad
-rw-r--r--vcl/Library_vclplug_gen.mk2
-rw-r--r--vcl/inc/generic/glyphcache.hxx1
-rw-r--r--vcl/inc/graphite_serverfont.hxx2
-rw-r--r--vcl/inc/textrender.hxx81
-rw-r--r--vcl/inc/unx/cairotextrender.hxx128
-rw-r--r--vcl/inc/unx/salgdi.h44
-rw-r--r--vcl/unx/generic/gdi/cairotextrender.cxx659
-rw-r--r--vcl/unx/generic/gdi/salgdi.cxx13
-rw-r--r--vcl/unx/generic/gdi/salgdi3.cxx590
-rw-r--r--vcl/unx/generic/gdi/x11cairotextrender.cxx96
-rw-r--r--vcl/unx/generic/gdi/x11cairotextrender.hxx39
11 files changed, 1038 insertions, 617 deletions
diff --git a/vcl/Library_vclplug_gen.mk b/vcl/Library_vclplug_gen.mk
index d25eec6248c2..fe9f4f6ddb16 100644
--- a/vcl/Library_vclplug_gen.mk
+++ b/vcl/Library_vclplug_gen.mk
@@ -88,6 +88,8 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gen,\
vcl/unx/generic/dtrans/X11_selection \
vcl/unx/generic/dtrans/X11_service \
vcl/unx/generic/dtrans/X11_transferable \
+ vcl/unx/generic/gdi/cairotextrender \
+ vcl/unx/generic/gdi/x11cairotextrender \
vcl/unx/generic/gdi/gcach_xpeer \
vcl/unx/generic/gdi/gdiimpl \
vcl/unx/generic/gdi/salbmp \
diff --git a/vcl/inc/generic/glyphcache.hxx b/vcl/inc/generic/glyphcache.hxx
index ba44ae8412b3..ddfc7a8ef965 100644
--- a/vcl/inc/generic/glyphcache.hxx
+++ b/vcl/inc/generic/glyphcache.hxx
@@ -205,6 +205,7 @@ private:
friend class ServerFontLayout;
friend class ImplServerFontEntry;
friend class X11SalGraphics;
+ friend class CairoTextRender;
void AddRef() const { ++mnRefCount; }
long GetRefCount() const { return mnRefCount; }
diff --git a/vcl/inc/graphite_serverfont.hxx b/vcl/inc/graphite_serverfont.hxx
index 0d533e00b7c2..7dfde21551bc 100644
--- a/vcl/inc/graphite_serverfont.hxx
+++ b/vcl/inc/graphite_serverfont.hxx
@@ -26,6 +26,8 @@
#ifndef _MSC_VER
#include <graphite_layout.hxx>
+#include "generic/glyphcache.hxx"
+
class PhysicalFontFace;
// Modules
diff --git a/vcl/inc/textrender.hxx b/vcl/inc/textrender.hxx
new file mode 100644
index 000000000000..b18b6300724b
--- /dev/null
+++ b/vcl/inc/textrender.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 .
+ */
+
+#ifndef INCLUDED_VCL_INC_UNX_CAIROFONTIMPL_HXX
+#define INCLUDED_VCL_INC_UNX_CAIROFONTIMPL_HXX
+
+#include <tools/rational.hxx>
+#include <vcl/salgtype.hxx>
+#include <vcl/vclenum.hxx>
+#include <vcl/metric.hxx>
+
+#include "salgdi.hxx"
+#include "salglyphid.hxx"
+#include "fontsubset.hxx"
+
+class PspSalPrinter;
+class PspSalInfoPrinter;
+class ServerFont;
+class ImplLayoutArgs;
+class ServerFontLayout;
+class PhysicalFontCollection;
+class PhysicalFontFace;
+
+class TextRenderImpl
+{
+public:
+ virtual ~TextRenderImpl() {}
+
+ virtual void SetTextColor( SalColor nSalColor ) = 0;
+ virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ) = 0;
+ virtual void GetFontMetric( ImplFontMetricData*, int nFallbackLevel ) = 0;
+ virtual const FontCharMapPtr GetFontCharMap() const = 0;
+ virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const = 0;
+ virtual void GetDevFontList( PhysicalFontCollection* ) = 0;
+ virtual void ClearDevFontCache() = 0;
+ virtual bool AddTempDevFont( PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) = 0;
+ virtual bool CreateFontSubset( const OUString& rToFile,
+ const PhysicalFontFace*,
+ sal_GlyphId* pGlyphIDs,
+ sal_uInt8* pEncoding,
+ sal_Int32* pWidths,
+ int nGlyphs,
+ FontSubsetInfo& rInfo
+ ) = 0;
+ virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded ) = 0;
+ virtual const void* GetEmbedFontData( const PhysicalFontFace*,
+ const sal_Ucs* pUnicodes,
+ sal_Int32* pWidths,
+ FontSubsetInfo& rInfo,
+ long* pDataLen ) = 0;
+ virtual void FreeEmbedFontData( const void* pData, long nDataLen ) = 0;
+ virtual void GetGlyphWidths( const PhysicalFontFace*,
+ bool bVertical,
+ Int32Vector& rWidths,
+ Ucs2UIntMap& rUnicodeEnc ) = 0;
+ virtual bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ) = 0;
+ virtual bool GetGlyphOutline( sal_GlyphId nIndex, ::basegfx::B2DPolyPolygon& ) = 0;
+ virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ) = 0;
+ virtual void DrawServerFontLayout( const ServerFontLayout& ) = 0;
+ virtual SystemFontData GetSysFontData( int nFallbackLevel ) const = 0;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/cairotextrender.hxx b/vcl/inc/unx/cairotextrender.hxx
new file mode 100644
index 000000000000..7bc0b2f7a36e
--- /dev/null
+++ b/vcl/inc/unx/cairotextrender.hxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 .
+ */
+
+#ifndef INCLUDED_VCL_INC_UNX_CAIROTEXTRENDER_HXX
+#define INCLUDED_VCL_INC_UNX_CAIROTEXTRENDER_HXX
+
+#include "textrender.hxx"
+#include <vcl/region.hxx>
+#include <deque>
+
+typedef struct FT_FaceRec_* FT_Face;
+
+class PspSalPrinter;
+class PspSalInfoPrinter;
+class ServerFont;
+class GlyphCache;
+class ImplLayoutArgs;
+class ServerFontLayout;
+class PhysicalFontCollection;
+class PhysicalFontFace;
+struct _cairo_surface_t;
+typedef struct _cairo_surface cairo_surface_t;
+typedef struct _cairo cairo_t;
+
+class CairoFontsCache
+{
+public:
+ struct CacheId
+ {
+ FT_Face maFace;
+ const void *mpOptions;
+ bool mbEmbolden;
+ bool mbVerticalMetrics;
+ bool operator ==(const CacheId& rOther) const
+ {
+ return maFace == rOther.maFace &&
+ mpOptions == rOther.mpOptions &&
+ mbEmbolden == rOther.mbEmbolden &&
+ mbVerticalMetrics == rOther.mbVerticalMetrics;
+ }
+ };
+private:
+ static int mnRefCount;
+ typedef std::deque< std::pair<void *, CacheId> > LRUFonts;
+ static LRUFonts maLRUFonts;
+public:
+ CairoFontsCache();
+ static void CacheFont(void *pFont, const CacheId &rId);
+ static void* FindCachedFont(const CacheId &rId);
+ ~CairoFontsCache();
+};
+
+class CairoTextRender : public TextRenderImpl
+{
+ bool mbPrinter;
+ ServerFont* mpServerFont[ MAX_FALLBACK ];
+
+ SalColor nTextColor_;
+ CairoFontsCache m_aCairoFontsCache;
+
+protected:
+ virtual GlyphCache& getPlatformGlyphCache() = 0;
+ virtual cairo_surface_t* getCairoSurface() = 0;
+
+bool setFont( const FontSelectPattern *pEntry, int nFallbackLevel );
+
+ virtual void clipRegion(cairo_t* cr) = 0;
+
+public:
+ CairoTextRender(bool bPrinter);
+
+
+ virtual void SetTextColor( SalColor nSalColor ) SAL_OVERRIDE;
+ virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ) SAL_OVERRIDE;
+ virtual void GetFontMetric( ImplFontMetricData*, int nFallbackLevel ) SAL_OVERRIDE;
+ virtual const FontCharMapPtr GetFontCharMap() const SAL_OVERRIDE;
+ virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const SAL_OVERRIDE;
+ virtual void GetDevFontList( PhysicalFontCollection* ) SAL_OVERRIDE;
+ virtual void ClearDevFontCache() SAL_OVERRIDE;
+ virtual bool AddTempDevFont( PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) SAL_OVERRIDE;
+ virtual bool CreateFontSubset( const OUString& rToFile,
+ const PhysicalFontFace*,
+ sal_GlyphId* pGlyphIDs,
+ sal_uInt8* pEncoding,
+ sal_Int32* pWidths,
+ int nGlyphs,
+ FontSubsetInfo& rInfo
+ ) SAL_OVERRIDE;
+ virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded ) SAL_OVERRIDE;
+ virtual const void* GetEmbedFontData( const PhysicalFontFace*,
+ const sal_Ucs* pUnicodes,
+ sal_Int32* pWidths,
+ FontSubsetInfo& rInfo,
+ long* pDataLen ) SAL_OVERRIDE;
+ virtual void FreeEmbedFontData( const void* pData, long nDataLen ) SAL_OVERRIDE;
+ virtual void GetGlyphWidths( const PhysicalFontFace*,
+ bool bVertical,
+ Int32Vector& rWidths,
+ Ucs2UIntMap& rUnicodeEnc ) SAL_OVERRIDE;
+ virtual bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ) SAL_OVERRIDE;
+ virtual bool GetGlyphOutline( sal_GlyphId nIndex, ::basegfx::B2DPolyPolygon& ) SAL_OVERRIDE;
+ virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ) SAL_OVERRIDE;
+ virtual void DrawServerFontLayout( const ServerFontLayout& ) SAL_OVERRIDE;
+ virtual SystemFontData GetSysFontData( int nFallbackLevel ) const SAL_OVERRIDE;
+
+private:
+ bool bDisableGraphite_;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 1e90e985d421..f79f6d97e054 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -52,48 +52,21 @@ class ServerFontLayout;
class PhysicalFontCollection;
class PhysicalFontFace;
class SalGraphicsImpl;
+class TextRenderImpl;
namespace basegfx {
class B2DTrapezoid;
}
-typedef struct FT_FaceRec_* FT_Face;
-
-class CairoFontsCache
-{
-public:
- struct CacheId
- {
- FT_Face maFace;
- const void *mpOptions;
- bool mbEmbolden;
- bool mbVerticalMetrics;
- bool operator ==(const CacheId& rOther) const
- {
- return maFace == rOther.maFace &&
- mpOptions == rOther.mpOptions &&
- mbEmbolden == rOther.mbEmbolden &&
- mbVerticalMetrics == rOther.mbVerticalMetrics;
- }
- };
-private:
- static int mnRefCount;
- typedef std::deque< std::pair<void *, CacheId> > LRUFonts;
- static LRUFonts maLRUFonts;
-public:
- CairoFontsCache();
- static void CacheFont(void *pFont, const CacheId &rId);
- static void* FindCachedFont(const CacheId &rId);
- ~CairoFontsCache();
-};
-
class VCLPLUG_GEN_PUBLIC X11SalGraphics : public SalGraphics
{
friend class ServerFontLayout;
friend class X11SalGraphicsImpl;
+ friend class X11CairoTextRender;
private:
boost::scoped_ptr<SalGraphicsImpl> mpImpl;
+ boost::scoped_ptr<TextRenderImpl> mpTextRenderImpl;
protected:
SalFrame* m_pFrame; // the SalFrame which created this Graphics or NULL
@@ -105,18 +78,12 @@ protected:
SalX11Screen m_nXScreen;
mutable XRenderPictFormat* m_pXRenderFormat;
XID m_aXRenderPicture;
- CairoFontsCache m_aCairoFontsCache;
Region pPaintRegion_;
Region mpClipRegion;
GC pFontGC_; // Font attributes
- ServerFont* mpServerFont[ MAX_FALLBACK ];
-
- SalColor nTextColor_;
- Pixel nTextPixel_;
-
- bool bDisableGraphite_;
+ Pixel nTextPixel_;
Pixmap hBrush_; // Dither
@@ -140,7 +107,6 @@ protected:
SalColor nTransparentColor );
GC GetFontGC();
- bool setFont( const FontSelectPattern* pEntry, int nFallbackLevel );
protected:
void DrawPrinterString( const SalLayout& );
@@ -294,7 +260,7 @@ public:
long nHeight, sal_uInt8 nTransparency ) SAL_OVERRIDE;
virtual SystemGraphicsData GetGraphicsData() const SAL_OVERRIDE;
- virtual SystemFontData GetSysFontData( int nFallbacklevel ) const SAL_OVERRIDE;
+ virtual SystemFontData GetSysFontData( int nFallbackLevel ) const SAL_OVERRIDE;
/* use to handle GraphicsExpose/NoExpose after XCopyArea & friends
* if pFrame is not NULL, corresponding Paint events are generated
diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx
new file mode 100644
index 000000000000..e4bee505e316
--- /dev/null
+++ b/vcl/unx/generic/gdi/cairotextrender.cxx
@@ -0,0 +1,659 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 "unx/cairotextrender.hxx"
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/sysdata.hxx>
+
+#include "generic/printergfx.hxx"
+#include "generic/genpspgraphics.h"
+#include "generic/geninst.h"
+#include "PhysicalFontFace.hxx"
+#include "impfont.hxx"
+
+#include <config_graphite.h>
+#if ENABLE_GRAPHITE
+#include <graphite_layout.hxx>
+#include <graphite_serverfont.hxx>
+#endif
+
+#include <cairo.h>
+#include <cairo-ft.h>
+#include <cairo-xlib.h>
+#include <cairo-xlib-xrender.h>
+
+CairoTextRender::CairoTextRender(bool bPrinter):
+ mbPrinter(bPrinter),
+ nTextColor_(MAKE_SALCOLOR(0x00, 0x00, 0x00)) //black
+{
+ for( int i = 0; i < MAX_FALLBACK; ++i )
+ mpServerFont[i] = NULL;
+
+#if ENABLE_GRAPHITE
+ // check if graphite fonts have been disabled
+ static const char* pDisableGraphiteStr = getenv( "SAL_DISABLE_GRAPHITE" );
+ bDisableGraphite_ = pDisableGraphiteStr && (pDisableGraphiteStr[0]!='0');
+#endif
+}
+
+bool CairoTextRender::setFont( const FontSelectPattern *pEntry, int nFallbackLevel )
+{
+ // release all no longer needed font resources
+ for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
+ {
+ if( mpServerFont[i] != NULL )
+ {
+ // old server side font is no longer referenced
+ GlyphCache::GetInstance().UncacheFont( *mpServerFont[i] );
+ mpServerFont[i] = NULL;
+ }
+ }
+
+ // return early if there is no new font
+ if( !pEntry )
+ return false;
+
+ // return early if this is not a valid font for this graphics
+ if( !pEntry->mpFontData )
+ return false;
+
+ // handle the request for a non-native X11-font => use the GlyphCache
+ ServerFont* pServerFont = GlyphCache::GetInstance().CacheFont( *pEntry );
+ if( pServerFont != NULL )
+ {
+ // ignore fonts with e.g. corrupted font files
+ if( !pServerFont->TestFont() )
+ {
+ GlyphCache::GetInstance().UncacheFont( *pServerFont );
+ return false;
+ }
+
+ // register to use the font
+ mpServerFont[ nFallbackLevel ] = pServerFont;
+
+ // apply font specific-hint settings if needed
+ // TODO: also disable it for reference devices
+ if( !mbPrinter )
+ {
+ ImplServerFontEntry* pSFE = static_cast<ImplServerFontEntry*>( pEntry->mpFontEntry );
+ pSFE->HandleFontOptions();
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+ImplFontOptions* GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize);
+
+void ImplServerFontEntry::HandleFontOptions( void )
+{
+ if( !mpServerFont )
+ return;
+ if( !mbGotFontOptions )
+ {
+ // get and cache the font options
+ mbGotFontOptions = true;
+ mpFontOptions.reset(GetFCFontOptions( *maFontSelData.mpFontData,
+ maFontSelData.mnHeight ));
+ }
+ // apply the font options
+ mpServerFont->SetFontOptions( mpFontOptions );
+}
+
+CairoFontsCache::LRUFonts CairoFontsCache::maLRUFonts;
+int CairoFontsCache::mnRefCount = 0;
+
+CairoFontsCache::CairoFontsCache()
+{
+ ++mnRefCount;
+}
+
+CairoFontsCache::~CairoFontsCache()
+{
+ --mnRefCount;
+ if (!mnRefCount && !maLRUFonts.empty())
+ {
+ LRUFonts::iterator aEnd = maLRUFonts.end();
+ for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
+ cairo_font_face_destroy((cairo_font_face_t*)aI->first);
+ }
+}
+
+void CairoFontsCache::CacheFont(void *pFont, const CairoFontsCache::CacheId &rId)
+{
+ maLRUFonts.push_front( std::pair<void*, CairoFontsCache::CacheId>(pFont, rId) );
+ if (maLRUFonts.size() > 8)
+ {
+ cairo_font_face_destroy((cairo_font_face_t*)maLRUFonts.back().first);
+ maLRUFonts.pop_back();
+ }
+}
+
+void* CairoFontsCache::FindCachedFont(const CairoFontsCache::CacheId &rId)
+{
+ LRUFonts::iterator aEnd = maLRUFonts.end();
+ for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
+ if (aI->second == rId)
+ return aI->first;
+ return NULL;
+}
+
+namespace
+{
+ bool hasRotation(int nRotation)
+ {
+ return nRotation != 0;
+ }
+
+ double toRadian(int nDegree10th)
+ {
+ return (3600 - (nDegree10th)) * M_PI / 1800.0;
+ }
+}
+
+void CairoTextRender::DrawServerFontLayout( const ServerFontLayout& rLayout )
+{
+ std::vector<cairo_glyph_t> cairo_glyphs;
+ std::vector<int> glyph_extrarotation;
+ cairo_glyphs.reserve( 256 );
+
+ Point aPos;
+ sal_GlyphId aGlyphId;
+ for( int nStart = 0; rLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart ); )
+ {
+ cairo_glyph_t aGlyph;
+ aGlyph.index = aGlyphId & GF_IDXMASK;
+ aGlyph.x = aPos.X();
+ aGlyph.y = aPos.Y();
+ cairo_glyphs.push_back(aGlyph);
+
+ switch (aGlyphId & GF_ROTMASK)
+ {
+ case GF_ROTL: // left
+ glyph_extrarotation.push_back(1);
+ break;
+ case GF_ROTR: // right
+ glyph_extrarotation.push_back(-1);
+ break;
+ default:
+ glyph_extrarotation.push_back(0);
+ break;
+ }
+ }
+
+ if (cairo_glyphs.empty())
+ return;
+
+ cairo_surface_t *surface = getCairoSurface();
+
+ DBG_ASSERT( surface!=NULL, "no cairo surface for text" );
+ if( !surface )
+ return;
+
+ /*
+ * It might be ideal to cache surface and cairo context between calls and
+ * only destroy it when the drawable changes, but to do that we need to at
+ * least change the SalFrame etc impls to dtor the SalGraphics *before* the
+ * destruction of the windows they reference
+ */
+ cairo_t *cr = cairo_create(surface);
+ cairo_surface_destroy(surface);
+
+ if (const void *pOptions = Application::GetSettings().GetStyleSettings().GetCairoFontOptions())
+ cairo_set_font_options(cr, static_cast<const cairo_font_options_t*>(pOptions));
+
+ clipRegion(cr);
+
+ cairo_set_source_rgb(cr,
+ SALCOLOR_RED(nTextColor_)/255.0,
+ SALCOLOR_GREEN(nTextColor_)/255.0,
+ SALCOLOR_BLUE(nTextColor_)/255.0);
+
+ ServerFont& rFont = rLayout.GetServerFont();
+
+ FT_Face aFace = rFont.GetFtFace();
+ CairoFontsCache::CacheId aId;
+ aId.maFace = aFace;
+ aId.mpOptions = rFont.GetFontOptions().get();
+ aId.mbEmbolden = rFont.NeedsArtificialBold();
+
+ cairo_matrix_t m;
+ const FontSelectPattern& rFSD = rFont.GetFontSelData();
+ int nHeight = rFSD.mnHeight;
+ int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight;
+
+ std::vector<int>::const_iterator aEnd = glyph_extrarotation.end();
+ std::vector<int>::const_iterator aStart = glyph_extrarotation.begin();
+ std::vector<int>::const_iterator aI = aStart;
+ while (aI != aEnd)
+ {
+ int nGlyphRotation = *aI;
+
+ std::vector<int>::const_iterator aNext = std::find_if(aI+1, aEnd, hasRotation);
+
+ size_t nStartIndex = std::distance(aStart, aI);
+ size_t nLen = std::distance(aI, aNext);
+
+ aId.mbVerticalMetrics = nGlyphRotation != 0.0;
+ cairo_font_face_t* font_face = (cairo_font_face_t*)CairoFontsCache::FindCachedFont(aId);
+ if (!font_face)
+ {
+ const ImplFontOptions *pOptions = rFont.GetFontOptions().get();
+ void *pPattern = pOptions ? pOptions->GetPattern(aFace, aId.mbEmbolden, aId.mbVerticalMetrics) : NULL;
+ if (pPattern)
+ font_face = cairo_ft_font_face_create_for_pattern(reinterpret_cast<FcPattern*>(pPattern));
+ if (!font_face)
+ font_face = cairo_ft_font_face_create_for_ft_face(reinterpret_cast<FT_Face>(aFace), rFont.GetLoadFlags());
+ CairoFontsCache::CacheFont(font_face, aId);
+ }
+ cairo_set_font_face(cr, font_face);
+
+ cairo_set_font_size(cr, nHeight);
+
+ cairo_matrix_init_identity(&m);
+
+ if (rLayout.GetOrientation())
+ cairo_matrix_rotate(&m, toRadian(rLayout.GetOrientation()));
+
+ cairo_matrix_scale(&m, nWidth, nHeight);
+
+ if (nGlyphRotation)
+ {
+ cairo_matrix_rotate(&m, toRadian(nGlyphRotation*900));
+
+ cairo_matrix_t em_square;
+ cairo_matrix_init_identity(&em_square);
+ cairo_get_matrix(cr, &em_square);
+
+ cairo_matrix_scale(&em_square, aFace->units_per_EM,
+ aFace->units_per_EM);
+ cairo_set_matrix(cr, &em_square);
+
+ cairo_font_extents_t font_extents;
+ cairo_font_extents(cr, &font_extents);
+
+ cairo_matrix_init_identity(&em_square);
+ cairo_set_matrix(cr, &em_square);
+
+ //gives the same positions as pre-cairo conversion, but I don't
+ //like them
+ double xdiff = 0.0;
+ double ydiff = 0.0;
+ if (nGlyphRotation == 1)
+ {
+ ydiff = font_extents.ascent/nHeight;
+ xdiff = -font_extents.descent/nHeight;
+ }
+ else if (nGlyphRotation == -1)
+ {
+ cairo_text_extents_t text_extents;
+ cairo_glyph_extents(cr, &cairo_glyphs[nStartIndex], nLen,
+ &text_extents);
+
+ xdiff = -text_extents.x_advance/nHeight;
+ //to restore an apparent bug in the original X11 impl, replace
+ //nHeight with nWidth below
+ xdiff += font_extents.descent/nHeight;
+ }
+ cairo_matrix_translate(&m, xdiff, ydiff);
+ }
+
+ if (rFont.NeedsArtificialItalic())
+ {
+ cairo_matrix_t shear;
+ cairo_matrix_init_identity(&shear);
+ shear.xy = -shear.xx * 0x6000L / 0x10000L;
+ cairo_matrix_multiply(&m, &shear, &m);
+ }
+
+ cairo_set_font_matrix(cr, &m);
+ cairo_show_glyphs(cr, &cairo_glyphs[nStartIndex], nLen);
+
+#if OSL_DEBUG_LEVEL > 2
+ //draw origin
+ cairo_save (cr);
+ cairo_rectangle (cr, cairo_glyphs[nStartIndex].x, cairo_glyphs[nStartIndex].y, 5, 5);
+ cairo_set_source_rgba (cr, 1, 0, 0, 0.80);
+ cairo_fill (cr);
+ cairo_restore (cr);
+#endif
+
+ aI = aNext;
+ }
+
+ cairo_destroy(cr);
+}
+
+const FontCharMapPtr CairoTextRender::GetFontCharMap() const
+{
+ if( !mpServerFont[0] )
+ return NULL;
+
+ const FontCharMapPtr pFCMap = mpServerFont[0]->GetFontCharMap();
+ return pFCMap;
+}
+
+bool CairoTextRender::GetFontCapabilities(vcl::FontCapabilities &rGetImplFontCapabilities) const
+{
+ if (!mpServerFont[0])
+ return false;
+ return mpServerFont[0]->GetFontCapabilities(rGetImplFontCapabilities);
+}
+
+// SalGraphics
+
+sal_uInt16 CairoTextRender::SetFont( FontSelectPattern *pEntry, int nFallbackLevel )
+{
+ sal_uInt16 nRetVal = 0;
+ if( !setFont( pEntry, nFallbackLevel ) )
+ nRetVal |= SAL_SETFONT_BADFONT;
+ if( mbPrinter || (mpServerFont[ nFallbackLevel ] != NULL) )
+ nRetVal |= SAL_SETFONT_USEDRAWTEXTARRAY;
+ return nRetVal;
+}
+
+void
+CairoTextRender::SetTextColor( SalColor nSalColor )
+{
+ if( nTextColor_ != nSalColor )
+ {
+ nTextColor_ = nSalColor;
+ }
+}
+
+bool CairoTextRender::AddTempDevFont( PhysicalFontCollection* pFontCollection,
+ const OUString& rFileURL,
+ const OUString& rFontName )
+{
+ // inform PSP font manager
+ OUString aUSystemPath;
+ OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFileURL, aUSystemPath ) );
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ OString aOFileName( OUStringToOString( aUSystemPath, aEncoding ) );
+ psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
+ std::vector<psp::fontID> aFontIds = rMgr.addFontFile( aOFileName );
+ if( aFontIds.empty() )
+ return false;
+
+ GlyphCache& rGC = getPlatformGlyphCache();
+
+ for (std::vector<psp::fontID>::iterator aI = aFontIds.begin(), aEnd = aFontIds.end(); aI != aEnd; ++aI)
+ {
+ // prepare font data
+ psp::FastPrintFontInfo aInfo;
+ rMgr.getFontFastInfo( *aI, aInfo );
+ aInfo.m_aFamilyName = rFontName;
+
+ // inform glyph cache of new font
+ ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
+ aDFA.mnQuality += 5800;
+
+ int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
+
+ const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
+ rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
+ }
+
+ // announce new font to device's font list
+ rGC.AnnounceFonts( pFontCollection );
+ return true;
+}
+
+void CairoTextRender::ClearDevFontCache()
+{
+ GlyphCache& rGC = getPlatformGlyphCache();
+ rGC.ClearFontCache();
+}
+
+void CairoTextRender::GetDevFontList( PhysicalFontCollection* pFontCollection )
+{
+ // prepare the GlyphCache using psprint's font infos
+ GlyphCache& rGC = getPlatformGlyphCache();
+
+ psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
+ ::std::list< psp::fontID > aList;
+ ::std::list< psp::fontID >::iterator it;
+ psp::FastPrintFontInfo aInfo;
+ rMgr.getFontList( aList );
+ for( it = aList.begin(); it != aList.end(); ++it )
+ {
+ if( !rMgr.getFontFastInfo( *it, aInfo ) )
+ continue;
+
+ // normalize face number to the GlyphCache
+ int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
+
+ // inform GlyphCache about this font provided by the PsPrint subsystem
+ ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
+ aDFA.mnQuality += 4096;
+ const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
+ rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
+ }
+
+ // announce glyphcache fonts
+ rGC.AnnounceFonts( pFontCollection );
+
+ // register platform specific font substitutions if available
+ SalGenericInstance::RegisterFontSubstitutors( pFontCollection );
+
+ ImplGetSVData()->maGDIData.mbNativeFontConfig = true;
+}
+
+void cairosubcallback(void* pPattern)
+{
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ const void* pFontOptions = rStyleSettings.GetCairoFontOptions();
+ if( !pFontOptions )
+ return;
+ cairo_ft_font_options_substitute(static_cast<const cairo_font_options_t*>(pFontOptions),
+ static_cast<FcPattern*>(pPattern));
+}
+
+ImplFontOptions* GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize)
+{
+ psp::FastPrintFontInfo aInfo;
+
+ aInfo.m_aFamilyName = rFontAttributes.GetFamilyName();
+ aInfo.m_eItalic = rFontAttributes.GetSlant();
+ aInfo.m_eWeight = rFontAttributes.GetWeight();
+ aInfo.m_eWidth = rFontAttributes.GetWidthType();
+
+ const psp::PrintFontManager& rPFM = psp::PrintFontManager::get();
+ return rPFM.getFontOptions(aInfo, nSize, cairosubcallback);
+}
+
+void
+CairoTextRender::GetFontMetric( ImplFontMetricData *pMetric, int nFallbackLevel )
+{
+ if( nFallbackLevel >= MAX_FALLBACK )
+ return;
+
+ if( mpServerFont[nFallbackLevel] != NULL )
+ {
+ long rDummyFactor;
+ mpServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor );
+ }
+}
+
+bool CairoTextRender::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect )
+{
+ const int nLevel = aGlyphId >> GF_FONTSHIFT;
+ if( nLevel >= MAX_FALLBACK )
+ return false;
+
+ ServerFont* pSF = mpServerFont[ nLevel ];
+ if( !pSF )
+ return false;
+
+ aGlyphId &= GF_IDXMASK;
+ const GlyphMetric& rGM = pSF->GetGlyphMetric(aGlyphId);
+ Rectangle aRect( rGM.GetOffset(), rGM.GetSize() );
+
+ if ( pSF->mnCos != 0x10000 && pSF->mnSin != 0 )
+ {
+ double nCos = pSF->mnCos / 65536.0;
+ double nSin = pSF->mnSin / 65536.0;
+ rRect.Left() = nCos*aRect.Left() + nSin*aRect.Top();
+ rRect.Top() = -nSin*aRect.Left() - nCos*aRect.Top();
+
+ rRect.Right() = nCos*aRect.Right() + nSin*aRect.Bottom();
+ rRect.Bottom() = -nSin*aRect.Right() - nCos*aRect.Bottom();
+ }
+ else
+ rRect = aRect;
+
+ return true;
+}
+
+bool CairoTextRender::GetGlyphOutline( sal_GlyphId aGlyphId,
+ ::basegfx::B2DPolyPolygon& rPolyPoly )
+{
+ const int nLevel = aGlyphId >> GF_FONTSHIFT;
+ if( nLevel >= MAX_FALLBACK )
+ return false;
+
+ ServerFont* pSF = mpServerFont[ nLevel ];
+ if( !pSF )
+ return false;
+
+ aGlyphId &= GF_IDXMASK;
+ if( pSF->GetGlyphOutline( aGlyphId, rPolyPoly ) )
+ return true;
+
+ return false;
+}
+
+SalLayout* CairoTextRender::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
+{
+ SalLayout* pLayout = NULL;
+
+ if( mpServerFont[ nFallbackLevel ]
+ && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
+ {
+#if ENABLE_GRAPHITE
+ // Is this a Graphite font?
+ if (!bDisableGraphite_ &&
+ GraphiteServerFontLayout::IsGraphiteEnabledFont(*mpServerFont[nFallbackLevel]))
+ {
+ pLayout = new GraphiteServerFontLayout(*mpServerFont[nFallbackLevel]);
+ }
+ else
+#endif
+ pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] );
+ }
+
+ return pLayout;
+}
+
+SystemFontData CairoTextRender::GetSysFontData( int nFallbackLevel ) const
+{
+ SystemFontData aSysFontData;
+ aSysFontData.nSize = sizeof( SystemFontData );
+ aSysFontData.nFontId = 0;
+
+ if (nFallbackLevel >= MAX_FALLBACK) nFallbackLevel = MAX_FALLBACK - 1;
+ if (nFallbackLevel < 0 ) nFallbackLevel = 0;
+
+ if (mpServerFont[nFallbackLevel] != NULL)
+ {
+ ServerFont* rFont = mpServerFont[nFallbackLevel];
+ aSysFontData.nFontId = rFont->GetFtFace();
+ aSysFontData.nFontFlags = rFont->GetLoadFlags();
+ aSysFontData.bFakeBold = rFont->NeedsArtificialBold();
+ aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic();
+ aSysFontData.bAntialias = rFont->GetAntialiasAdvice();
+ aSysFontData.bVerticalCharacterType = rFont->GetFontSelData().mbVertical;
+ }
+
+ return aSysFontData;
+}
+
+bool CairoTextRender::CreateFontSubset(
+ const OUString& rToFile,
+ const PhysicalFontFace* pFont,
+ sal_GlyphId* pGlyphIds,
+ sal_uInt8* pEncoding,
+ sal_Int32* pWidths,
+ int nGlyphCount,
+ FontSubsetInfo& rInfo
+ )
+{
+ // in this context the pFont->GetFontId() is a valid PSP
+ // font since they are the only ones left after the PDF
+ // export has filtered its list of subsettable fonts (for
+ // which this method was created). The correct way would
+ // be to have the GlyphCache search for the PhysicalFontFace pFont
+ psp::fontID aFont = pFont->GetFontId();
+
+ psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
+ bool bSuccess = rMgr.createFontSubset( rInfo,
+ aFont,
+ rToFile,
+ pGlyphIds,
+ pEncoding,
+ pWidths,
+ nGlyphCount );
+ return bSuccess;
+}
+
+const void* CairoTextRender::GetEmbedFontData( const PhysicalFontFace* pFont, const sal_Ucs* pUnicodes, sal_Int32* pWidths, FontSubsetInfo& rInfo, long* pDataLen )
+{
+ // in this context the pFont->GetFontId() is a valid PSP
+ // font since they are the only ones left after the PDF
+ // export has filtered its list of subsettable fonts (for
+ // which this method was created). The correct way would
+ // be to have the GlyphCache search for the PhysicalFontFace pFont
+ psp::fontID aFont = pFont->GetFontId();
+ return GenPspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
+}
+
+void CairoTextRender::FreeEmbedFontData( const void* pData, long nLen )
+{
+ GenPspGraphics::DoFreeEmbedFontData( pData, nLen );
+}
+
+const Ucs2SIntMap* CairoTextRender::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
+{
+ // in this context the pFont->GetFontId() is a valid PSP
+ // font since they are the only ones left after the PDF
+ // export has filtered its list of subsettable fonts (for
+ // which this method was created). The correct way would
+ // be to have the GlyphCache search for the PhysicalFontFace pFont
+ psp::fontID aFont = pFont->GetFontId();
+ return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
+}
+
+void CairoTextRender::GetGlyphWidths( const PhysicalFontFace* pFont,
+ bool bVertical,
+ Int32Vector& rWidths,
+ Ucs2UIntMap& rUnicodeEnc )
+{
+ // in this context the pFont->GetFontId() is a valid PSP
+ // font since they are the only ones left after the PDF
+ // export has filtered its list of subsettable fonts (for
+ // which this method was created). The correct way would
+ // be to have the GlyphCache search for the PhysicalFontFace pFont
+ psp::fontID aFont = pFont->GetFontId();
+ GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index c5dd0bedd54a..02598c3a0a63 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -52,6 +52,7 @@
#include "salgdiimpl.hxx"
#include "unx/x11windowprovider.hxx"
+#include "textrender.hxx"
#include "gdiimpl.hxx"
#include "openglgdiimpl.hxx"
@@ -74,7 +75,6 @@ X11SalGraphics::X11SalGraphics():
pPaintRegion_(NULL),
mpClipRegion(NULL),
pFontGC_(NULL),
- nTextColor_(MAKE_SALCOLOR(0x00, 0x00, 0x00)), //black
nTextPixel_(0),
hBrush_(None),
bWindow_(false),
@@ -87,15 +87,6 @@ X11SalGraphics::X11SalGraphics():
mpImpl.reset(new OpenGLSalGraphicsImpl());
else
mpImpl.reset(new X11SalGraphicsImpl(*this));
-
- for( int i = 0; i < MAX_FALLBACK; ++i )
- mpServerFont[i] = NULL;
-
-#if ENABLE_GRAPHITE
- // check if graphite fonts have been disabled
- static const char* pDisableGraphiteStr = getenv( "SAL_DISABLE_GRAPHITE" );
- bDisableGraphite_ = pDisableGraphiteStr && (pDisableGraphiteStr[0]!='0');
-#endif
}
X11SalGraphics::~X11SalGraphics()
@@ -164,7 +155,7 @@ void X11SalGraphics::SetDrawable( Drawable aDrawable, SalX11Screen nXScreen )
aWin, m_nXScreen.getXScreen());
}
}
- nTextPixel_ = GetPixel( nTextColor_ );
+ // TODO: moggi: FIXME nTextPixel_ = GetPixel( nTextColor_ );
}
}
diff --git a/vcl/unx/generic/gdi/salgdi3.cxx b/vcl/unx/generic/gdi/salgdi3.cxx
index 3cd42cdd09a9..3f47712e68ba 100644
--- a/vcl/unx/generic/gdi/salgdi3.cxx
+++ b/vcl/unx/generic/gdi/salgdi3.cxx
@@ -36,7 +36,6 @@
#include <osl/module.hxx>
#include <rtl/tencinfo.h>
#include <sal/alloca.h>
-#include <tools/debug.hxx>
#include <tools/stream.hxx>
#include <vcl/settings.hxx>
#include <vcl/sysdata.hxx>
@@ -59,31 +58,9 @@
#include "unx/salgdi.h"
#include "unx/salunx.h"
#include "unx/salvd.h"
+#include "textrender.hxx"
#include "xrender_peer.hxx"
-#include <config_graphite.h>
-#if ENABLE_GRAPHITE
-#include <graphite_layout.hxx>
-#include <graphite_serverfont.hxx>
-#endif
-
-#include <cairo.h>
-#include <cairo-ft.h>
-#include <cairo-xlib.h>
-#include <cairo-xlib-xrender.h>
-
-struct BOX
-{
- short x1, x2, y1, y2;
-};
-struct _XRegion
-{
- long size;
- long numRects;
- BOX *rects;
- BOX extents;
-};
-
// X11SalGraphics
GC
@@ -113,569 +90,80 @@ X11SalGraphics::GetFontGC()
return pFontGC_;
}
-bool X11SalGraphics::setFont( const FontSelectPattern *pEntry, int nFallbackLevel )
-{
- // release all no longer needed font resources
- for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
- {
- if( mpServerFont[i] != NULL )
- {
- // old server side font is no longer referenced
- GlyphCache::GetInstance().UncacheFont( *mpServerFont[i] );
- mpServerFont[i] = NULL;
- }
- }
-
- // return early if there is no new font
- if( !pEntry )
- return false;
-
- // return early if this is not a valid font for this graphics
- if( !pEntry->mpFontData )
- return false;
-
- // handle the request for a non-native X11-font => use the GlyphCache
- ServerFont* pServerFont = GlyphCache::GetInstance().CacheFont( *pEntry );
- if( pServerFont != NULL )
- {
- // ignore fonts with e.g. corrupted font files
- if( !pServerFont->TestFont() )
- {
- GlyphCache::GetInstance().UncacheFont( *pServerFont );
- return false;
- }
-
- // register to use the font
- mpServerFont[ nFallbackLevel ] = pServerFont;
-
- // apply font specific-hint settings if needed
- // TODO: also disable it for reference devices
- if( !bPrinter_ )
- {
- ImplServerFontEntry* pSFE = static_cast<ImplServerFontEntry*>( pEntry->mpFontEntry );
- pSFE->HandleFontOptions();
- }
-
- return true;
- }
-
- return false;
-}
-
ImplFontOptions* GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize);
-void ImplServerFontEntry::HandleFontOptions( void )
-{
- if( !mpServerFont )
- return;
- if( !mbGotFontOptions )
- {
- // get and cache the font options
- mbGotFontOptions = true;
- mpFontOptions.reset(GetFCFontOptions( *maFontSelData.mpFontData,
- maFontSelData.mnHeight ));
- }
- // apply the font options
- mpServerFont->SetFontOptions( mpFontOptions );
-}
-
-CairoFontsCache::LRUFonts CairoFontsCache::maLRUFonts;
-int CairoFontsCache::mnRefCount = 0;
-
-CairoFontsCache::CairoFontsCache()
-{
- ++mnRefCount;
-}
-
-CairoFontsCache::~CairoFontsCache()
-{
- --mnRefCount;
- if (!mnRefCount && !maLRUFonts.empty())
- {
- LRUFonts::iterator aEnd = maLRUFonts.end();
- for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
- cairo_font_face_destroy((cairo_font_face_t*)aI->first);
- }
-}
-
-void CairoFontsCache::CacheFont(void *pFont, const CairoFontsCache::CacheId &rId)
-{
- maLRUFonts.push_front( std::pair<void*, CairoFontsCache::CacheId>(pFont, rId) );
- if (maLRUFonts.size() > 8)
- {
- cairo_font_face_destroy((cairo_font_face_t*)maLRUFonts.back().first);
- maLRUFonts.pop_back();
- }
-}
-
-void* CairoFontsCache::FindCachedFont(const CairoFontsCache::CacheId &rId)
-{
- LRUFonts::iterator aEnd = maLRUFonts.end();
- for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
- if (aI->second == rId)
- return aI->first;
- return NULL;
-}
-
-namespace
-{
- bool hasRotation(int nRotation)
- {
- return nRotation != 0;
- }
-
- double toRadian(int nDegree10th)
- {
- return (3600 - (nDegree10th)) * M_PI / 1800.0;
- }
-}
-
void X11SalGraphics::DrawServerFontLayout( const ServerFontLayout& rLayout )
{
- std::vector<cairo_glyph_t> cairo_glyphs;
- std::vector<int> glyph_extrarotation;
- cairo_glyphs.reserve( 256 );
-
- Point aPos;
- sal_GlyphId aGlyphId;
- for( int nStart = 0; rLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart ); )
- {
- cairo_glyph_t aGlyph;
- aGlyph.index = aGlyphId & GF_IDXMASK;
- aGlyph.x = aPos.X();
- aGlyph.y = aPos.Y();
- cairo_glyphs.push_back(aGlyph);
-
- switch (aGlyphId & GF_ROTMASK)
- {
- case GF_ROTL: // left
- glyph_extrarotation.push_back(1);
- break;
- case GF_ROTR: // right
- glyph_extrarotation.push_back(-1);
- break;
- default:
- glyph_extrarotation.push_back(0);
- break;
- }
- }
-
- if (cairo_glyphs.empty())
- return;
-
- // find a XRenderPictFormat compatible with the Drawable
- XRenderPictFormat* pVisualFormat = GetXRenderFormat();
-
- Display* pDisplay = GetXDisplay();
-
- cairo_surface_t *surface;
-
- if (pVisualFormat)
- {
- surface = cairo_xlib_surface_create_with_xrender_format (
- pDisplay, hDrawable_,
- ScreenOfDisplay(pDisplay, m_nXScreen.getXScreen()),
- pVisualFormat, SAL_MAX_INT16, SAL_MAX_INT16);
- }
- else
- {
- surface = cairo_xlib_surface_create(pDisplay, hDrawable_,
- GetVisual().visual, SAL_MAX_INT16, SAL_MAX_INT16);
- }
-
- DBG_ASSERT( surface!=NULL, "no cairo surface for text" );
- if( !surface )
- return;
-
- /*
- * It might be ideal to cache surface and cairo context between calls and
- * only destroy it when the drawable changes, but to do that we need to at
- * least change the SalFrame etc impls to dtor the SalGraphics *before* the
- * destruction of the windows they reference
- */
- cairo_t *cr = cairo_create(surface);
- cairo_surface_destroy(surface);
-
- if (const void *pOptions = Application::GetSettings().GetStyleSettings().GetCairoFontOptions())
- cairo_set_font_options(cr, static_cast<const cairo_font_options_t*>(pOptions));
-
- if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
- {
- for (long i = 0; i < mpClipRegion->numRects; ++i)
- {
- cairo_rectangle(cr,
- mpClipRegion->rects[i].x1,
- mpClipRegion->rects[i].y1,
- mpClipRegion->rects[i].x2 - mpClipRegion->rects[i].x1,
- mpClipRegion->rects[i].y2 - mpClipRegion->rects[i].y1);
- }
- cairo_clip(cr);
- }
-
- cairo_set_source_rgb(cr,
- SALCOLOR_RED(nTextColor_)/255.0,
- SALCOLOR_GREEN(nTextColor_)/255.0,
- SALCOLOR_BLUE(nTextColor_)/255.0);
-
- ServerFont& rFont = rLayout.GetServerFont();
-
- FT_Face aFace = rFont.GetFtFace();
- CairoFontsCache::CacheId aId;
- aId.maFace = aFace;
- aId.mpOptions = rFont.GetFontOptions().get();
- aId.mbEmbolden = rFont.NeedsArtificialBold();
-
- cairo_matrix_t m;
- const FontSelectPattern& rFSD = rFont.GetFontSelData();
- int nHeight = rFSD.mnHeight;
- int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight;
-
- std::vector<int>::const_iterator aEnd = glyph_extrarotation.end();
- std::vector<int>::const_iterator aStart = glyph_extrarotation.begin();
- std::vector<int>::const_iterator aI = aStart;
- while (aI != aEnd)
- {
- int nGlyphRotation = *aI;
-
- std::vector<int>::const_iterator aNext = std::find_if(aI+1, aEnd, hasRotation);
-
- size_t nStartIndex = std::distance(aStart, aI);
- size_t nLen = std::distance(aI, aNext);
-
- aId.mbVerticalMetrics = nGlyphRotation != 0.0;
- cairo_font_face_t* font_face = (cairo_font_face_t*)CairoFontsCache::FindCachedFont(aId);
- if (!font_face)
- {
- const ImplFontOptions *pOptions = rFont.GetFontOptions().get();
- void *pPattern = pOptions ? pOptions->GetPattern(aFace, aId.mbEmbolden, aId.mbVerticalMetrics) : NULL;
- if (pPattern)
- font_face = cairo_ft_font_face_create_for_pattern(reinterpret_cast<FcPattern*>(pPattern));
- if (!font_face)
- font_face = cairo_ft_font_face_create_for_ft_face(reinterpret_cast<FT_Face>(aFace), rFont.GetLoadFlags());
- CairoFontsCache::CacheFont(font_face, aId);
- }
- cairo_set_font_face(cr, font_face);
-
- cairo_set_font_size(cr, nHeight);
-
- cairo_matrix_init_identity(&m);
-
- if (rLayout.GetOrientation())
- cairo_matrix_rotate(&m, toRadian(rLayout.GetOrientation()));
-
- cairo_matrix_scale(&m, nWidth, nHeight);
-
- if (nGlyphRotation)
- {
- cairo_matrix_rotate(&m, toRadian(nGlyphRotation*900));
-
- cairo_matrix_t em_square;
- cairo_matrix_init_identity(&em_square);
- cairo_get_matrix(cr, &em_square);
-
- cairo_matrix_scale(&em_square, aFace->units_per_EM,
- aFace->units_per_EM);
- cairo_set_matrix(cr, &em_square);
-
- cairo_font_extents_t font_extents;
- cairo_font_extents(cr, &font_extents);
-
- cairo_matrix_init_identity(&em_square);
- cairo_set_matrix(cr, &em_square);
-
- //gives the same positions as pre-cairo conversion, but I don't
- //like them
- double xdiff = 0.0;
- double ydiff = 0.0;
- if (nGlyphRotation == 1)
- {
- ydiff = font_extents.ascent/nHeight;
- xdiff = -font_extents.descent/nHeight;
- }
- else if (nGlyphRotation == -1)
- {
- cairo_text_extents_t text_extents;
- cairo_glyph_extents(cr, &cairo_glyphs[nStartIndex], nLen,
- &text_extents);
-
- xdiff = -text_extents.x_advance/nHeight;
- //to restore an apparent bug in the original X11 impl, replace
- //nHeight with nWidth below
- xdiff += font_extents.descent/nHeight;
- }
- cairo_matrix_translate(&m, xdiff, ydiff);
- }
-
- if (rFont.NeedsArtificialItalic())
- {
- cairo_matrix_t shear;
- cairo_matrix_init_identity(&shear);
- shear.xy = -shear.xx * 0x6000L / 0x10000L;
- cairo_matrix_multiply(&m, &shear, &m);
- }
-
- cairo_set_font_matrix(cr, &m);
- cairo_show_glyphs(cr, &cairo_glyphs[nStartIndex], nLen);
-
-#if OSL_DEBUG_LEVEL > 2
- //draw origin
- cairo_save (cr);
- cairo_rectangle (cr, cairo_glyphs[nStartIndex].x, cairo_glyphs[nStartIndex].y, 5, 5);
- cairo_set_source_rgba (cr, 1, 0, 0, 0.80);
- cairo_fill (cr);
- cairo_restore (cr);
-#endif
-
- aI = aNext;
- }
-
- cairo_destroy(cr);
+ mpTextRenderImpl->DrawServerFontLayout(rLayout);
}
const FontCharMapPtr X11SalGraphics::GetFontCharMap() const
{
- if( !mpServerFont[0] )
- return NULL;
-
- const FontCharMapPtr pFCMap = mpServerFont[0]->GetFontCharMap();
- return pFCMap;
+ return mpTextRenderImpl->GetFontCharMap();
}
bool X11SalGraphics::GetFontCapabilities(vcl::FontCapabilities &rGetImplFontCapabilities) const
{
- if (!mpServerFont[0])
- return false;
- return mpServerFont[0]->GetFontCapabilities(rGetImplFontCapabilities);
+ return mpTextRenderImpl->GetFontCapabilities(rGetImplFontCapabilities);
}
// SalGraphics
sal_uInt16 X11SalGraphics::SetFont( FontSelectPattern *pEntry, int nFallbackLevel )
{
- sal_uInt16 nRetVal = 0;
- if( !setFont( pEntry, nFallbackLevel ) )
- nRetVal |= SAL_SETFONT_BADFONT;
- if( bPrinter_ || (mpServerFont[ nFallbackLevel ] != NULL) )
- nRetVal |= SAL_SETFONT_USEDRAWTEXTARRAY;
- return nRetVal;
+ return mpTextRenderImpl->SetFont(pEntry, nFallbackLevel);
}
void
X11SalGraphics::SetTextColor( SalColor nSalColor )
{
- if( nTextColor_ != nSalColor )
- {
- nTextColor_ = nSalColor;
- nTextPixel_ = GetPixel( nSalColor );
- bFontGC_ = false;
- }
+ mpTextRenderImpl->SetTextColor(nSalColor);
+ nTextPixel_ = GetPixel( nSalColor );
+ bFontGC_ = false;
}
bool X11SalGraphics::AddTempDevFont( PhysicalFontCollection* pFontCollection,
const OUString& rFileURL,
const OUString& rFontName )
{
- // inform PSP font manager
- OUString aUSystemPath;
- OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFileURL, aUSystemPath ) );
- rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
- OString aOFileName( OUStringToOString( aUSystemPath, aEncoding ) );
- psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
- std::vector<psp::fontID> aFontIds = rMgr.addFontFile( aOFileName );
- if( aFontIds.empty() )
- return false;
-
- GlyphCache& rGC = X11GlyphCache::GetInstance();
-
- for (std::vector<psp::fontID>::iterator aI = aFontIds.begin(), aEnd = aFontIds.end(); aI != aEnd; ++aI)
- {
- // prepare font data
- psp::FastPrintFontInfo aInfo;
- rMgr.getFontFastInfo( *aI, aInfo );
- aInfo.m_aFamilyName = rFontName;
-
- // inform glyph cache of new font
- ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
- aDFA.mnQuality += 5800;
-
- int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
-
- const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
- rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
- }
-
- // announce new font to device's font list
- rGC.AnnounceFonts( pFontCollection );
- return true;
+ return mpTextRenderImpl->AddTempDevFont(pFontCollection, rFileURL, rFontName);
}
void X11SalGraphics::ClearDevFontCache()
{
- X11GlyphCache& rGC = X11GlyphCache::GetInstance();
- rGC.ClearFontCache();
+ mpTextRenderImpl->ClearDevFontCache();
}
void X11SalGraphics::GetDevFontList( PhysicalFontCollection* pFontCollection )
{
- // prepare the GlyphCache using psprint's font infos
- X11GlyphCache& rGC = X11GlyphCache::GetInstance();
-
- psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
- ::std::list< psp::fontID > aList;
- ::std::list< psp::fontID >::iterator it;
- psp::FastPrintFontInfo aInfo;
- rMgr.getFontList( aList );
- for( it = aList.begin(); it != aList.end(); ++it )
- {
- if( !rMgr.getFontFastInfo( *it, aInfo ) )
- continue;
-
- // normalize face number to the GlyphCache
- int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
-
- // inform GlyphCache about this font provided by the PsPrint subsystem
- ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
- aDFA.mnQuality += 4096;
- const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
- rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
- }
-
- // announce glyphcache fonts
- rGC.AnnounceFonts( pFontCollection );
-
- // register platform specific font substitutions if available
- SalGenericInstance::RegisterFontSubstitutors( pFontCollection );
-
- ImplGetSVData()->maGDIData.mbNativeFontConfig = true;
-}
-
-void cairosubcallback(void* pPattern)
-{
- const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
- const void* pFontOptions = rStyleSettings.GetCairoFontOptions();
- if( !pFontOptions )
- return;
- cairo_ft_font_options_substitute(static_cast<const cairo_font_options_t*>(pFontOptions),
- static_cast<FcPattern*>(pPattern));
-}
-
-ImplFontOptions* GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize)
-{
- psp::FastPrintFontInfo aInfo;
-
- aInfo.m_aFamilyName = rFontAttributes.GetFamilyName();
- aInfo.m_eItalic = rFontAttributes.GetSlant();
- aInfo.m_eWeight = rFontAttributes.GetWeight();
- aInfo.m_eWidth = rFontAttributes.GetWidthType();
-
- const psp::PrintFontManager& rPFM = psp::PrintFontManager::get();
- return rPFM.getFontOptions(aInfo, nSize, cairosubcallback);
+ mpTextRenderImpl->GetDevFontList(pFontCollection);
}
void
X11SalGraphics::GetFontMetric( ImplFontMetricData *pMetric, int nFallbackLevel )
{
- if( nFallbackLevel >= MAX_FALLBACK )
- return;
-
- if( mpServerFont[nFallbackLevel] != NULL )
- {
- long rDummyFactor;
- mpServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor );
- }
+ mpTextRenderImpl->GetFontMetric(pMetric, nFallbackLevel);
}
bool X11SalGraphics::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect )
{
- const int nLevel = aGlyphId >> GF_FONTSHIFT;
- if( nLevel >= MAX_FALLBACK )
- return false;
-
- ServerFont* pSF = mpServerFont[ nLevel ];
- if( !pSF )
- return false;
-
- aGlyphId &= GF_IDXMASK;
- const GlyphMetric& rGM = pSF->GetGlyphMetric(aGlyphId);
- Rectangle aRect( rGM.GetOffset(), rGM.GetSize() );
-
- if ( pSF->mnCos != 0x10000 && pSF->mnSin != 0 )
- {
- double nCos = pSF->mnCos / 65536.0;
- double nSin = pSF->mnSin / 65536.0;
- rRect.Left() = nCos*aRect.Left() + nSin*aRect.Top();
- rRect.Top() = -nSin*aRect.Left() - nCos*aRect.Top();
-
- rRect.Right() = nCos*aRect.Right() + nSin*aRect.Bottom();
- rRect.Bottom() = -nSin*aRect.Right() - nCos*aRect.Bottom();
- }
- else
- rRect = aRect;
-
- return true;
+ return mpTextRenderImpl->GetGlyphBoundRect(aGlyphId, rRect);
}
bool X11SalGraphics::GetGlyphOutline( sal_GlyphId aGlyphId,
::basegfx::B2DPolyPolygon& rPolyPoly )
{
- const int nLevel = aGlyphId >> GF_FONTSHIFT;
- if( nLevel >= MAX_FALLBACK )
- return false;
-
- ServerFont* pSF = mpServerFont[ nLevel ];
- if( !pSF )
- return false;
-
- aGlyphId &= GF_IDXMASK;
- if( pSF->GetGlyphOutline( aGlyphId, rPolyPoly ) )
- return true;
-
- return false;
+ return mpTextRenderImpl->GetGlyphOutline(aGlyphId, rPolyPoly);
}
SalLayout* X11SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
{
- SalLayout* pLayout = NULL;
-
- if( mpServerFont[ nFallbackLevel ]
- && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
- {
-#if ENABLE_GRAPHITE
- // Is this a Graphite font?
- if (!bDisableGraphite_ &&
- GraphiteServerFontLayout::IsGraphiteEnabledFont(*mpServerFont[nFallbackLevel]))
- {
- pLayout = new GraphiteServerFontLayout(*mpServerFont[nFallbackLevel]);
- }
- else
-#endif
- pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] );
- }
-
- return pLayout;
+ return mpTextRenderImpl->GetTextLayout(rArgs, nFallbackLevel);
}
-SystemFontData X11SalGraphics::GetSysFontData( int nFallbacklevel ) const
+SystemFontData X11SalGraphics::GetSysFontData( int nFallbackLevel ) const
{
- SystemFontData aSysFontData;
- aSysFontData.nSize = sizeof( SystemFontData );
- aSysFontData.nFontId = 0;
-
- if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
- if (nFallbacklevel < 0 ) nFallbacklevel = 0;
-
- if (mpServerFont[nFallbacklevel] != NULL)
- {
- ServerFont* rFont = mpServerFont[nFallbacklevel];
- aSysFontData.nFontId = rFont->GetFtFace();
- aSysFontData.nFontFlags = rFont->GetLoadFlags();
- aSysFontData.bFakeBold = rFont->NeedsArtificialBold();
- aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic();
- aSysFontData.bAntialias = rFont->GetAntialiasAdvice();
- aSysFontData.bVerticalCharacterType = rFont->GetFontSelData().mbVertical;
- }
-
- return aSysFontData;
+ return mpTextRenderImpl->GetSysFontData(nFallbackLevel);
}
bool X11SalGraphics::CreateFontSubset(
@@ -688,49 +176,23 @@ bool X11SalGraphics::CreateFontSubset(
FontSubsetInfo& rInfo
)
{
- // in this context the pFont->GetFontId() is a valid PSP
- // font since they are the only ones left after the PDF
- // export has filtered its list of subsettable fonts (for
- // which this method was created). The correct way would
- // be to have the GlyphCache search for the PhysicalFontFace pFont
- psp::fontID aFont = pFont->GetFontId();
-
- psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
- bool bSuccess = rMgr.createFontSubset( rInfo,
- aFont,
- rToFile,
- pGlyphIds,
- pEncoding,
- pWidths,
- nGlyphCount );
- return bSuccess;
+ return mpTextRenderImpl->CreateFontSubset(rToFile, pFont,
+ pGlyphIds, pEncoding, pWidths, nGlyphCount, rInfo);
}
const void* X11SalGraphics::GetEmbedFontData( const PhysicalFontFace* pFont, const sal_Ucs* pUnicodes, sal_Int32* pWidths, FontSubsetInfo& rInfo, long* pDataLen )
{
- // in this context the pFont->GetFontId() is a valid PSP
- // font since they are the only ones left after the PDF
- // export has filtered its list of subsettable fonts (for
- // which this method was created). The correct way would
- // be to have the GlyphCache search for the PhysicalFontFace pFont
- psp::fontID aFont = pFont->GetFontId();
- return GenPspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
+ return mpTextRenderImpl->GetEmbedFontData(pFont, pUnicodes, pWidths, rInfo, pDataLen);
}
void X11SalGraphics::FreeEmbedFontData( const void* pData, long nLen )
{
- GenPspGraphics::DoFreeEmbedFontData( pData, nLen );
+ mpTextRenderImpl->FreeEmbedFontData(pData, nLen);
}
const Ucs2SIntMap* X11SalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
{
- // in this context the pFont->GetFontId() is a valid PSP
- // font since they are the only ones left after the PDF
- // export has filtered its list of subsettable fonts (for
- // which this method was created). The correct way would
- // be to have the GlyphCache search for the PhysicalFontFace pFont
- psp::fontID aFont = pFont->GetFontId();
- return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
+ return mpTextRenderImpl->GetFontEncodingVector(pFont, pNonEncoded);
}
void X11SalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont,
@@ -738,13 +200,7 @@ void X11SalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont,
Int32Vector& rWidths,
Ucs2UIntMap& rUnicodeEnc )
{
- // in this context the pFont->GetFontId() is a valid PSP
- // font since they are the only ones left after the PDF
- // export has filtered its list of subsettable fonts (for
- // which this method was created). The correct way would
- // be to have the GlyphCache search for the PhysicalFontFace pFont
- psp::fontID aFont = pFont->GetFontId();
- GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
+ mpTextRenderImpl->GetGlyphWidths(pFont, bVertical, rWidths, rUnicodeEnc);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/x11cairotextrender.cxx b/vcl/unx/generic/gdi/x11cairotextrender.cxx
new file mode 100644
index 000000000000..3a21c390a357
--- /dev/null
+++ b/vcl/unx/generic/gdi/x11cairotextrender.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 "x11cairotextrender.hxx"
+#include "unx/saldata.hxx"
+#include "unx/saldisp.hxx"
+
+#include "gcach_xpeer.hxx"
+
+#include <cairo.h>
+#include <cairo-ft.h>
+
+#include <cairo-xlib.h>
+#include <cairo-xlib-xrender.h>
+
+struct BOX
+{
+ short x1, x2, y1, y2;
+};
+struct _XRegion
+{
+ long size;
+ long numRects;
+ BOX *rects;
+ BOX extents;
+};
+
+X11CairoTextRender::X11CairoTextRender(bool bPrinter, X11SalGraphics& rParent):
+ CairoTextRender(bPrinter),
+ mrParent(rParent)
+{
+}
+
+GlyphCache& X11CairoTextRender::getPlatformGlyphCache()
+{
+ return X11GlyphCache::GetInstance();
+}
+
+cairo_surface_t* X11CairoTextRender::getCairoSurface()
+{
+ // find a XRenderPictFormat compatible with the Drawable
+ XRenderPictFormat* pVisualFormat = mrParent.GetXRenderFormat();
+
+ Display* pDisplay = mrParent.GetXDisplay();
+
+ cairo_surface_t* surface = NULL;
+ if (pVisualFormat)
+ {
+ surface = cairo_xlib_surface_create_with_xrender_format (
+ pDisplay, mrParent.hDrawable_,
+ ScreenOfDisplay(pDisplay, mrParent.m_nXScreen.getXScreen()),
+ pVisualFormat, SAL_MAX_INT16, SAL_MAX_INT16);
+ }
+ else
+ {
+ surface = cairo_xlib_surface_create(pDisplay, mrParent.hDrawable_,
+ mrParent.GetVisual().visual, SAL_MAX_INT16, SAL_MAX_INT16);
+ }
+
+ return surface;
+}
+
+void X11CairoTextRender::clipRegion(cairo_t* cr)
+{
+ Region pClipRegion = mrParent.mpClipRegion;
+ if( pClipRegion && !XEmptyRegion( pClipRegion ) )
+ {
+ for (long i = 0; i < pClipRegion->numRects; ++i)
+ {
+ cairo_rectangle(cr,
+ pClipRegion->rects[i].x1,
+ pClipRegion->rects[i].y1,
+ pClipRegion->rects[i].x2 - pClipRegion->rects[i].x1,
+ pClipRegion->rects[i].y2 - pClipRegion->rects[i].y1);
+ }
+ cairo_clip(cr);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/x11cairotextrender.hxx b/vcl/unx/generic/gdi/x11cairotextrender.hxx
new file mode 100644
index 000000000000..eb4410250944
--- /dev/null
+++ b/vcl/unx/generic/gdi/x11cairotextrender.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 "unx/cairotextrender.hxx"
+
+#include "unx/saldata.hxx"
+#include "unx/saldisp.hxx"
+
+#include "unx/salgdi.h"
+
+class X11CairoTextRender : public CairoTextRender
+{
+private:
+ X11SalGraphics& mrParent;
+public:
+ X11CairoTextRender(bool bPrinter, X11SalGraphics& rParent);
+
+ virtual GlyphCache& getPlatformGlyphCache() SAL_OVERRIDE;
+ virtual cairo_surface_t* getCairoSurface() SAL_OVERRIDE;
+ virtual void clipRegion(cairo_t* cr) SAL_OVERRIDE;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */