diff options
-rw-r--r-- | vcl/Library_vclplug_gen.mk | 2 | ||||
-rw-r--r-- | vcl/inc/generic/glyphcache.hxx | 1 | ||||
-rw-r--r-- | vcl/inc/graphite_serverfont.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/textrender.hxx | 81 | ||||
-rw-r--r-- | vcl/inc/unx/cairotextrender.hxx | 128 | ||||
-rw-r--r-- | vcl/inc/unx/salgdi.h | 44 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/cairotextrender.cxx | 659 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/salgdi.cxx | 13 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/salgdi3.cxx | 590 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/x11cairotextrender.cxx | 96 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/x11cairotextrender.hxx | 39 |
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: */ |