1c82f2877SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3c82f2877SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4c82f2877SAndrew Rist * or more contributor license agreements. See the NOTICE file 5c82f2877SAndrew Rist * distributed with this work for additional information 6c82f2877SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7c82f2877SAndrew Rist * to you under the Apache License, Version 2.0 (the 8c82f2877SAndrew Rist * "License"); you may not use this file except in compliance 9c82f2877SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11c82f2877SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13c82f2877SAndrew Rist * Unless required by applicable law or agreed to in writing, 14c82f2877SAndrew Rist * software distributed under the License is distributed on an 15c82f2877SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16c82f2877SAndrew Rist * KIND, either express or implied. See the License for the 17c82f2877SAndrew Rist * specific language governing permissions and limitations 18c82f2877SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20c82f2877SAndrew Rist *************************************************************/ 21c82f2877SAndrew Rist 22c82f2877SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_vcl.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <string.h> 28cdf0e10cSrcweir #include <stdio.h> 29cdf0e10cSrcweir #include <stdlib.h> 30cdf0e10cSrcweir #include <math.h> 31cdf0e10cSrcweir #include <unistd.h> 32cdf0e10cSrcweir #include <fcntl.h> 33cdf0e10cSrcweir #include <sys/mman.h> 34cdf0e10cSrcweir #include <sys/stat.h> 35cdf0e10cSrcweir #include <sys/types.h> 36cdf0e10cSrcweir 37cdf0e10cSrcweir #include "sal/alloca.h" 38cdf0e10cSrcweir #include "sal/types.h" 39cdf0e10cSrcweir 40cdf0e10cSrcweir #include "rtl/tencinfo.h" 41cdf0e10cSrcweir 42cdf0e10cSrcweir #include "osl/file.hxx" 43cdf0e10cSrcweir 44cdf0e10cSrcweir #include "tools/string.hxx" 45cdf0e10cSrcweir #include "tools/debug.hxx" 46cdf0e10cSrcweir #include "tools/stream.hxx" 47cdf0e10cSrcweir 48cdf0e10cSrcweir #include "basegfx/polygon/b2dpolypolygon.hxx" 49cdf0e10cSrcweir 50cdf0e10cSrcweir #include "i18npool/mslangid.hxx" 51cdf0e10cSrcweir 52cdf0e10cSrcweir #include <vcl/sysdata.hxx> 53cdf0e10cSrcweir #include "printergfx.hxx" 54cdf0e10cSrcweir #include "vcl/fontmanager.hxx" 55cdf0e10cSrcweir #include "vcl/jobdata.hxx" 56cdf0e10cSrcweir #include "vcl/printerinfomanager.hxx" 57cdf0e10cSrcweir #include "vcl/svapp.hxx" 58cdf0e10cSrcweir 59cdf0e10cSrcweir #include "unx/salunx.h" 60cdf0e10cSrcweir #include "unx/saldata.hxx" 61cdf0e10cSrcweir #include "unx/saldisp.hxx" 62cdf0e10cSrcweir #include "unx/salgdi.h" 63cdf0e10cSrcweir #include "unx/pspgraphics.h" 64cdf0e10cSrcweir #include "unx/salvd.h" 65cdf0e10cSrcweir 66cdf0e10cSrcweir #include "salcvt.hxx" 67cdf0e10cSrcweir #include "gcach_xpeer.hxx" 68cdf0e10cSrcweir #include "xrender_peer.hxx" 69cdf0e10cSrcweir #include "impfont.hxx" 70cdf0e10cSrcweir #include "salframe.hxx" 71cdf0e10cSrcweir #include "outdev.h" 72cdf0e10cSrcweir 73cdf0e10cSrcweir 74cdf0e10cSrcweir #include <hash_set> 75cdf0e10cSrcweir 76cdf0e10cSrcweir #ifdef ENABLE_GRAPHITE 77cdf0e10cSrcweir #include <graphite_layout.hxx> 78cdf0e10cSrcweir #include <graphite_serverfont.hxx> 79cdf0e10cSrcweir #endif 80cdf0e10cSrcweir 81cdf0e10cSrcweir struct cairo_surface_t; 82cdf0e10cSrcweir struct cairo_t; 83cdf0e10cSrcweir struct cairo_font_face_t; 84cdf0e10cSrcweir typedef void* FT_Face; 85cdf0e10cSrcweir struct cairo_matrix_t { 86cdf0e10cSrcweir double xx; double yx; 87cdf0e10cSrcweir double xy; double yy; 88cdf0e10cSrcweir double x0; double y0; 89cdf0e10cSrcweir }; 90cdf0e10cSrcweir struct cairo_glyph_t 91cdf0e10cSrcweir { 92cdf0e10cSrcweir unsigned long index; 93cdf0e10cSrcweir double x; 94cdf0e10cSrcweir double y; 95cdf0e10cSrcweir }; 96cdf0e10cSrcweir struct BOX 97cdf0e10cSrcweir { 98cdf0e10cSrcweir short x1, x2, y1, y2; 99cdf0e10cSrcweir }; 100cdf0e10cSrcweir struct _XRegion 101cdf0e10cSrcweir { 102cdf0e10cSrcweir long size; 103cdf0e10cSrcweir long numRects; 104cdf0e10cSrcweir BOX *rects; 105cdf0e10cSrcweir BOX extents; 106cdf0e10cSrcweir }; 107cdf0e10cSrcweir using namespace rtl; 108cdf0e10cSrcweir 109cdf0e10cSrcweir // =========================================================================== 110cdf0e10cSrcweir 111cdf0e10cSrcweir // PspKernInfo allows on-demand-querying of psprint provided kerning info (#i29881#) 112cdf0e10cSrcweir class PspKernInfo : public ExtraKernInfo 113cdf0e10cSrcweir { 114cdf0e10cSrcweir public: 115cdf0e10cSrcweir PspKernInfo( int nFontId ) : ExtraKernInfo(nFontId) {} 116cdf0e10cSrcweir protected: 117cdf0e10cSrcweir virtual void Initialize() const; 118cdf0e10cSrcweir }; 119cdf0e10cSrcweir 120cdf0e10cSrcweir //-------------------------------------------------------------------------- 121cdf0e10cSrcweir 122cdf0e10cSrcweir void PspKernInfo::Initialize() const 123cdf0e10cSrcweir { 124cdf0e10cSrcweir mbInitialized = true; 125cdf0e10cSrcweir 126cdf0e10cSrcweir // get the kerning pairs from psprint 127cdf0e10cSrcweir const psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); 128cdf0e10cSrcweir typedef std::list< psp::KernPair > PspKernPairs; 129cdf0e10cSrcweir const PspKernPairs& rKernPairs = rMgr.getKernPairs( mnFontId ); 130cdf0e10cSrcweir if( rKernPairs.empty() ) 131cdf0e10cSrcweir return; 132cdf0e10cSrcweir 133cdf0e10cSrcweir // feed psprint's kerning list into a lookup-friendly container 134*b4fbd7a9SHerbert Dürr maUnicodeKernPairs.rehash( rKernPairs.size() ); 135cdf0e10cSrcweir PspKernPairs::const_iterator it = rKernPairs.begin(); 136cdf0e10cSrcweir for(; it != rKernPairs.end(); ++it ) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir ImplKernPairData aKernPair = { it->first, it->second, it->kern_x }; 139cdf0e10cSrcweir maUnicodeKernPairs.insert( aKernPair ); 140cdf0e10cSrcweir } 141cdf0e10cSrcweir } 142cdf0e10cSrcweir 143cdf0e10cSrcweir // ---------------------------------------------------------------------------- 144cdf0e10cSrcweir // 145cdf0e10cSrcweir // X11SalGraphics 146cdf0e10cSrcweir // 147cdf0e10cSrcweir // ---------------------------------------------------------------------------- 148cdf0e10cSrcweir 149cdf0e10cSrcweir GC 150cdf0e10cSrcweir X11SalGraphics::GetFontGC() 151cdf0e10cSrcweir { 152cdf0e10cSrcweir Display *pDisplay = GetXDisplay(); 153cdf0e10cSrcweir 154cdf0e10cSrcweir if( !pFontGC_ ) 155cdf0e10cSrcweir { 156cdf0e10cSrcweir XGCValues values; 157cdf0e10cSrcweir values.subwindow_mode = ClipByChildren; 158cdf0e10cSrcweir values.fill_rule = EvenOddRule; // Pict import/ Gradient 159cdf0e10cSrcweir values.graphics_exposures = False; 160cdf0e10cSrcweir values.foreground = nTextPixel_; 161cdf0e10cSrcweir pFontGC_ = XCreateGC( pDisplay, hDrawable_, 162cdf0e10cSrcweir GCSubwindowMode | GCFillRule 163cdf0e10cSrcweir | GCGraphicsExposures | GCForeground, 164cdf0e10cSrcweir &values ); 165cdf0e10cSrcweir } 166cdf0e10cSrcweir if( !bFontGC_ ) 167cdf0e10cSrcweir { 168cdf0e10cSrcweir XSetForeground( pDisplay, pFontGC_, nTextPixel_ ); 169cdf0e10cSrcweir SetClipRegion( pFontGC_ ); 170cdf0e10cSrcweir bFontGC_ = sal_True; 171cdf0e10cSrcweir } 172cdf0e10cSrcweir 173cdf0e10cSrcweir return pFontGC_; 174cdf0e10cSrcweir } 175cdf0e10cSrcweir 176cdf0e10cSrcweir //-------------------------------------------------------------------------- 177cdf0e10cSrcweir 178cdf0e10cSrcweir bool X11SalGraphics::setFont( const ImplFontSelectData *pEntry, int nFallbackLevel ) 179cdf0e10cSrcweir { 180cdf0e10cSrcweir #ifdef HDU_DEBUG 181cdf0e10cSrcweir ByteString aReqName( "NULL" ); 182cdf0e10cSrcweir if( pEntry ) 183cdf0e10cSrcweir aReqName = ByteString( pEntry->maName, RTL_TEXTENCODING_UTF8 ); 184cdf0e10cSrcweir ByteString aUseName( "NULL" ); 185cdf0e10cSrcweir if( pEntry && pEntry->mpFontData ) 186cdf0e10cSrcweir aUseName = ByteString( pEntry->mpFontData->GetFamilyName(), RTL_TEXTENCODING_UTF8 ); 187cdf0e10cSrcweir fprintf( stderr, "SetFont(lvl=%d,\"%s\", %d*%d, naa=%d,b=%d,i=%d) => \"%s\"\n", 188cdf0e10cSrcweir nFallbackLevel, aReqName.GetBuffer(), 189cdf0e10cSrcweir !pEntry?-1:pEntry->mnWidth, !pEntry?-1:pEntry->mnHeight, 190cdf0e10cSrcweir !pEntry?-1:pEntry->mbNonAntialiased, 191cdf0e10cSrcweir !pEntry?-1:pEntry->meWeight, !pEntry?-1:pEntry->meItalic, 192cdf0e10cSrcweir aUseName.GetBuffer() ); 193cdf0e10cSrcweir #endif 194cdf0e10cSrcweir 195cdf0e10cSrcweir // release all no longer needed font resources 196cdf0e10cSrcweir for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) 197cdf0e10cSrcweir { 198cdf0e10cSrcweir if( mpServerFont[i] != NULL ) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir // old server side font is no longer referenced 201cdf0e10cSrcweir GlyphCache::GetInstance().UncacheFont( *mpServerFont[i] ); 202cdf0e10cSrcweir mpServerFont[i] = NULL; 203cdf0e10cSrcweir } 204cdf0e10cSrcweir } 205cdf0e10cSrcweir 206cdf0e10cSrcweir // return early if there is no new font 207cdf0e10cSrcweir if( !pEntry ) 208cdf0e10cSrcweir return false; 209cdf0e10cSrcweir 210cdf0e10cSrcweir bFontVertical_ = pEntry->mbVertical; 211cdf0e10cSrcweir 212cdf0e10cSrcweir // return early if this is not a valid font for this graphics 213cdf0e10cSrcweir if( !pEntry->mpFontData ) 214cdf0e10cSrcweir return false; 215cdf0e10cSrcweir 216cdf0e10cSrcweir // handle the request for a non-native X11-font => use the GlyphCache 217cdf0e10cSrcweir ServerFont* pServerFont = GlyphCache::GetInstance().CacheFont( *pEntry ); 218cdf0e10cSrcweir if( pServerFont != NULL ) 219cdf0e10cSrcweir { 220cdf0e10cSrcweir // ignore fonts with e.g. corrupted font files 221cdf0e10cSrcweir if( !pServerFont->TestFont() ) 222cdf0e10cSrcweir { 223cdf0e10cSrcweir GlyphCache::GetInstance().UncacheFont( *pServerFont ); 224cdf0e10cSrcweir return false; 225cdf0e10cSrcweir } 226cdf0e10cSrcweir 227cdf0e10cSrcweir // register to use the font 228cdf0e10cSrcweir mpServerFont[ nFallbackLevel ] = pServerFont; 229cdf0e10cSrcweir 230cdf0e10cSrcweir // apply font specific-hint settings if needed 231cdf0e10cSrcweir // TODO: also disable it for reference devices 232cdf0e10cSrcweir if( !bPrinter_ ) 233cdf0e10cSrcweir { 234cdf0e10cSrcweir ImplServerFontEntry* pSFE = static_cast<ImplServerFontEntry*>( pEntry->mpFontEntry ); 235cdf0e10cSrcweir pSFE->HandleFontOptions(); 236cdf0e10cSrcweir } 237cdf0e10cSrcweir 238cdf0e10cSrcweir return true; 239cdf0e10cSrcweir } 240cdf0e10cSrcweir 241cdf0e10cSrcweir return false; 242cdf0e10cSrcweir } 243cdf0e10cSrcweir 244cdf0e10cSrcweir void ImplServerFontEntry::HandleFontOptions( void ) 245cdf0e10cSrcweir { 246cdf0e10cSrcweir bool GetFCFontOptions( const ImplFontAttributes&, int nSize, ImplFontOptions& ); 247cdf0e10cSrcweir 248cdf0e10cSrcweir if( !mpServerFont ) 249cdf0e10cSrcweir return; 250cdf0e10cSrcweir if( !mbGotFontOptions ) 251cdf0e10cSrcweir { 252cdf0e10cSrcweir // get and cache the font options 253cdf0e10cSrcweir mbGotFontOptions = true; 254cdf0e10cSrcweir mbValidFontOptions = GetFCFontOptions( *maFontSelData.mpFontData, 255cdf0e10cSrcweir maFontSelData.mnHeight, maFontOptions ); 256cdf0e10cSrcweir } 257cdf0e10cSrcweir // apply the font options 258cdf0e10cSrcweir if( mbValidFontOptions ) 259cdf0e10cSrcweir mpServerFont->SetFontOptions( maFontOptions ); 260cdf0e10cSrcweir } 261cdf0e10cSrcweir 262cdf0e10cSrcweir //-------------------------------------------------------------------------- 263cdf0e10cSrcweir 264cdf0e10cSrcweir namespace { 265cdf0e10cSrcweir 266cdf0e10cSrcweir class CairoWrapper 267cdf0e10cSrcweir { 268cdf0e10cSrcweir private: 269cdf0e10cSrcweir oslModule mpCairoLib; 270cdf0e10cSrcweir 271cdf0e10cSrcweir cairo_surface_t* (*mp_xlib_surface_create_with_xrender_format)(Display *, Drawable , Screen *, XRenderPictFormat *, int , int ); 272cdf0e10cSrcweir void (*mp_surface_destroy)(cairo_surface_t *); 273cdf0e10cSrcweir cairo_t* (*mp_create)(cairo_surface_t *); 274cdf0e10cSrcweir void (*mp_destroy)(cairo_t*); 275cdf0e10cSrcweir void (*mp_clip)(cairo_t*); 276cdf0e10cSrcweir void (*mp_rectangle)(cairo_t*, double, double, double, double); 277cdf0e10cSrcweir cairo_font_face_t * (*mp_ft_font_face_create_for_ft_face)(FT_Face, int); 278cdf0e10cSrcweir void (*mp_set_font_face)(cairo_t *, cairo_font_face_t *); 279cdf0e10cSrcweir void (*mp_font_face_destroy)(cairo_font_face_t *); 280cdf0e10cSrcweir void (*mp_matrix_init_identity)(cairo_matrix_t *); 281cdf0e10cSrcweir void (*mp_matrix_scale)(cairo_matrix_t *, double, double); 282cdf0e10cSrcweir void (*mp_matrix_rotate)(cairo_matrix_t *, double); 283cdf0e10cSrcweir void (*mp_set_font_matrix)(cairo_t *, const cairo_matrix_t *); 284cdf0e10cSrcweir void (*mp_show_glyphs)(cairo_t *, const cairo_glyph_t *, int ); 285cdf0e10cSrcweir void (*mp_set_source_rgb)(cairo_t *, double , double , double ); 286cdf0e10cSrcweir void (*mp_set_font_options)(cairo_t *, const void *); 287cdf0e10cSrcweir void (*mp_ft_font_options_substitute)(const void*, void*); 288cdf0e10cSrcweir 289cdf0e10cSrcweir bool canEmbolden() const { return false; } 290cdf0e10cSrcweir 291cdf0e10cSrcweir CairoWrapper(); 292cdf0e10cSrcweir public: 293cdf0e10cSrcweir static CairoWrapper& get(); 294cdf0e10cSrcweir bool isValid() const { return (mpCairoLib != NULL); } 295cdf0e10cSrcweir bool isCairoRenderable(const ServerFont& rFont); 296cdf0e10cSrcweir 297cdf0e10cSrcweir cairo_surface_t* xlib_surface_create_with_xrender_format(Display *pDisplay, Drawable drawable, Screen *pScreen, XRenderPictFormat *pFormat, int width, int height) 298cdf0e10cSrcweir { return (*mp_xlib_surface_create_with_xrender_format)(pDisplay, drawable, pScreen, pFormat, width, height); } 299cdf0e10cSrcweir void surface_destroy(cairo_surface_t *surface) { (*mp_surface_destroy)(surface); } 300cdf0e10cSrcweir cairo_t* create(cairo_surface_t *surface) { return (*mp_create)(surface); } 301cdf0e10cSrcweir void destroy(cairo_t *cr) { (*mp_destroy)(cr); } 302cdf0e10cSrcweir void clip(cairo_t *cr) { (*mp_clip)(cr); } 303cdf0e10cSrcweir void rectangle(cairo_t *cr, double x, double y, double width, double height) 304cdf0e10cSrcweir { (*mp_rectangle)(cr, x, y, width, height); } 305cdf0e10cSrcweir cairo_font_face_t* ft_font_face_create_for_ft_face(FT_Face face, int load_flags) 306cdf0e10cSrcweir { return (*mp_ft_font_face_create_for_ft_face)(face, load_flags); } 307cdf0e10cSrcweir void set_font_face(cairo_t *cr, cairo_font_face_t *font_face) 308cdf0e10cSrcweir { (*mp_set_font_face)(cr, font_face); } 309cdf0e10cSrcweir void font_face_destroy(cairo_font_face_t *font_face) 310cdf0e10cSrcweir { (*mp_font_face_destroy)(font_face); } 311cdf0e10cSrcweir void matrix_init_identity(cairo_matrix_t *matrix) 312cdf0e10cSrcweir { (*mp_matrix_init_identity)(matrix); } 313cdf0e10cSrcweir void matrix_scale(cairo_matrix_t *matrix, double sx, double sy) 314cdf0e10cSrcweir { (*mp_matrix_scale)(matrix, sx, sy); } 315cdf0e10cSrcweir void matrix_rotate(cairo_matrix_t *matrix, double radians) 316cdf0e10cSrcweir { (*mp_matrix_rotate)(matrix, radians); } 317cdf0e10cSrcweir void set_font_matrix(cairo_t *cr, const cairo_matrix_t *matrix) 318cdf0e10cSrcweir { (*mp_set_font_matrix)(cr, matrix); } 319cdf0e10cSrcweir void show_glyphs(cairo_t *cr, const cairo_glyph_t *glyphs, int no_glyphs) 320cdf0e10cSrcweir { (*mp_show_glyphs)(cr, glyphs, no_glyphs); } 321cdf0e10cSrcweir void set_source_rgb(cairo_t *cr, double red, double green, double blue) 322cdf0e10cSrcweir { (*mp_set_source_rgb)(cr, red, green, blue); } 323cdf0e10cSrcweir void set_font_options(cairo_t *cr, const void *options) 324cdf0e10cSrcweir { (*mp_set_font_options)(cr, options); } 325cdf0e10cSrcweir void ft_font_options_substitute(const void *options, void *pattern) 326cdf0e10cSrcweir { (*mp_ft_font_options_substitute)(options, pattern); } 327cdf0e10cSrcweir }; 328cdf0e10cSrcweir 329cdf0e10cSrcweir static CairoWrapper* pCairoInstance = NULL; 330cdf0e10cSrcweir 331cdf0e10cSrcweir CairoWrapper& CairoWrapper::get() 332cdf0e10cSrcweir { 333cdf0e10cSrcweir if( ! pCairoInstance ) 334cdf0e10cSrcweir pCairoInstance = new CairoWrapper(); 335cdf0e10cSrcweir return *pCairoInstance; 336cdf0e10cSrcweir } 337cdf0e10cSrcweir 338cdf0e10cSrcweir CairoWrapper::CairoWrapper() 339cdf0e10cSrcweir : mpCairoLib( NULL ) 340cdf0e10cSrcweir { 341cdf0e10cSrcweir static const char* pDisableCairoText = getenv( "SAL_DISABLE_CAIROTEXT" ); 342cdf0e10cSrcweir if( pDisableCairoText && (pDisableCairoText[0] != '0') ) 343cdf0e10cSrcweir return; 344cdf0e10cSrcweir 345cdf0e10cSrcweir int nDummy; 346cdf0e10cSrcweir if( !XQueryExtension( GetX11SalData()->GetDisplay()->GetDisplay(), "RENDER", &nDummy, &nDummy, &nDummy ) ) 347cdf0e10cSrcweir return; 348cdf0e10cSrcweir 349aa150a94SHerbert Dürr mpCairoLib = osl_loadAsciiModule( "libcairo.so.2", SAL_LOADMODULE_DEFAULT ); 350cdf0e10cSrcweir if( !mpCairoLib ) 351cdf0e10cSrcweir return; 352cdf0e10cSrcweir 353cdf0e10cSrcweir #ifdef DEBUG 354cdf0e10cSrcweir // check cairo version 355cdf0e10cSrcweir int (*p_version)(); 356cdf0e10cSrcweir p_version = (int(*)()) osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_version" ); 357cdf0e10cSrcweir const int nVersion = p_version ? (*p_version)() : 0; 358cdf0e10cSrcweir fprintf( stderr, "CAIRO version=%d\n", nVersion ); 359cdf0e10cSrcweir #endif 360cdf0e10cSrcweir 361cdf0e10cSrcweir mp_xlib_surface_create_with_xrender_format = (cairo_surface_t* (*)(Display *, Drawable , Screen *, XRenderPictFormat *, int , int )) 362cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_xlib_surface_create_with_xrender_format" ); 363cdf0e10cSrcweir mp_surface_destroy = (void(*)(cairo_surface_t*)) 364cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_surface_destroy" ); 365cdf0e10cSrcweir mp_create = (cairo_t*(*)(cairo_surface_t*)) 366cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_create" ); 367cdf0e10cSrcweir mp_destroy = (void(*)(cairo_t*)) 368cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_destroy" ); 369cdf0e10cSrcweir mp_clip = (void(*)(cairo_t*)) 370cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_clip" ); 371cdf0e10cSrcweir mp_rectangle = (void(*)(cairo_t*, double, double, double, double)) 372cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_rectangle" ); 373cdf0e10cSrcweir mp_ft_font_face_create_for_ft_face = (cairo_font_face_t * (*)(FT_Face, int)) 374cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_ft_font_face_create_for_ft_face" ); 375cdf0e10cSrcweir mp_set_font_face = (void (*)(cairo_t *, cairo_font_face_t *)) 376cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_font_face" ); 377cdf0e10cSrcweir mp_font_face_destroy = (void (*)(cairo_font_face_t *)) 378cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_font_face_destroy" ); 379cdf0e10cSrcweir mp_matrix_init_identity = (void (*)(cairo_matrix_t *)) 380cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_matrix_init_identity" ); 381cdf0e10cSrcweir mp_matrix_scale = (void (*)(cairo_matrix_t *, double, double)) 382cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_matrix_scale" ); 383cdf0e10cSrcweir mp_matrix_rotate = (void (*)(cairo_matrix_t *, double)) 384cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_matrix_rotate" ); 385cdf0e10cSrcweir mp_set_font_matrix = (void (*)(cairo_t *, const cairo_matrix_t *)) 386cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_font_matrix" ); 387cdf0e10cSrcweir mp_show_glyphs = (void (*)(cairo_t *, const cairo_glyph_t *, int )) 388cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_show_glyphs" ); 389cdf0e10cSrcweir mp_set_source_rgb = (void (*)(cairo_t *, double , double , double )) 390cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_source_rgb" ); 391cdf0e10cSrcweir mp_set_font_options = (void (*)(cairo_t *, const void *options )) 392cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_font_options" ); 393cdf0e10cSrcweir mp_ft_font_options_substitute = (void (*)(const void *, void *)) 394cdf0e10cSrcweir osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_ft_font_options_substitute" ); 395cdf0e10cSrcweir 396cdf0e10cSrcweir if( !( 397cdf0e10cSrcweir mp_xlib_surface_create_with_xrender_format && 398cdf0e10cSrcweir mp_surface_destroy && 399cdf0e10cSrcweir mp_create && 400cdf0e10cSrcweir mp_destroy && 401cdf0e10cSrcweir mp_clip && 402cdf0e10cSrcweir mp_rectangle && 403cdf0e10cSrcweir mp_ft_font_face_create_for_ft_face && 404cdf0e10cSrcweir mp_set_font_face && 405cdf0e10cSrcweir mp_font_face_destroy && 406cdf0e10cSrcweir mp_matrix_init_identity && 407cdf0e10cSrcweir mp_matrix_scale && 408cdf0e10cSrcweir mp_matrix_rotate && 409cdf0e10cSrcweir mp_set_font_matrix && 410cdf0e10cSrcweir mp_show_glyphs && 411cdf0e10cSrcweir mp_set_source_rgb && 412cdf0e10cSrcweir mp_set_font_options && 413cdf0e10cSrcweir mp_ft_font_options_substitute 414cdf0e10cSrcweir ) ) 415cdf0e10cSrcweir { 416cdf0e10cSrcweir osl_unloadModule( mpCairoLib ); 417cdf0e10cSrcweir mpCairoLib = NULL; 418cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 419cdf0e10cSrcweir fprintf( stderr, "not all needed symbols were found\n" ); 420cdf0e10cSrcweir #endif 421cdf0e10cSrcweir } 422cdf0e10cSrcweir } 423cdf0e10cSrcweir 424cdf0e10cSrcweir bool CairoWrapper::isCairoRenderable(const ServerFont& rFont) 425cdf0e10cSrcweir { 426cdf0e10cSrcweir return rFont.GetFtFace() && isValid() && rFont.GetAntialiasAdvice() && 427cdf0e10cSrcweir (rFont.NeedsArtificialBold() ? canEmbolden() : true); 428cdf0e10cSrcweir } 429cdf0e10cSrcweir 430cdf0e10cSrcweir } //namespace 431cdf0e10cSrcweir 432cdf0e10cSrcweir CairoFontsCache::LRUFonts CairoFontsCache::maLRUFonts; 433cdf0e10cSrcweir int CairoFontsCache::mnRefCount = 0; 434cdf0e10cSrcweir 435cdf0e10cSrcweir CairoFontsCache::CairoFontsCache() 436cdf0e10cSrcweir { 437cdf0e10cSrcweir ++mnRefCount; 438cdf0e10cSrcweir } 439cdf0e10cSrcweir 440cdf0e10cSrcweir CairoFontsCache::~CairoFontsCache() 441cdf0e10cSrcweir { 442cdf0e10cSrcweir --mnRefCount; 443cdf0e10cSrcweir if (!mnRefCount && !maLRUFonts.empty()) 444cdf0e10cSrcweir { 445cdf0e10cSrcweir CairoWrapper &rCairo = CairoWrapper::get(); 446cdf0e10cSrcweir LRUFonts::iterator aEnd = maLRUFonts.end(); 447cdf0e10cSrcweir for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI) 448cdf0e10cSrcweir rCairo.font_face_destroy((cairo_font_face_t*)aI->first); 449cdf0e10cSrcweir } 450cdf0e10cSrcweir } 451cdf0e10cSrcweir 452cdf0e10cSrcweir void CairoFontsCache::CacheFont(void *pFont, void* pId) 453cdf0e10cSrcweir { 454cdf0e10cSrcweir maLRUFonts.push_front( std::pair<void*, void *>(pFont, pId) ); 455cdf0e10cSrcweir if (maLRUFonts.size() > 8) 456cdf0e10cSrcweir { 457cdf0e10cSrcweir CairoWrapper &rCairo = CairoWrapper::get(); 458cdf0e10cSrcweir rCairo.font_face_destroy((cairo_font_face_t*)maLRUFonts.back().first); 459cdf0e10cSrcweir maLRUFonts.pop_back(); 460cdf0e10cSrcweir } 461cdf0e10cSrcweir } 462cdf0e10cSrcweir 463cdf0e10cSrcweir void* CairoFontsCache::FindCachedFont(void *pId) 464cdf0e10cSrcweir { 465cdf0e10cSrcweir LRUFonts::iterator aEnd = maLRUFonts.end(); 466cdf0e10cSrcweir for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI) 467cdf0e10cSrcweir if (aI->second == pId) 468cdf0e10cSrcweir return aI->first; 469cdf0e10cSrcweir return NULL; 470cdf0e10cSrcweir } 471cdf0e10cSrcweir 472cdf0e10cSrcweir void X11SalGraphics::DrawCairoAAFontString( const ServerFontLayout& rLayout ) 473cdf0e10cSrcweir { 474cdf0e10cSrcweir std::vector<cairo_glyph_t> cairo_glyphs; 475cdf0e10cSrcweir cairo_glyphs.reserve( 256 ); 476cdf0e10cSrcweir 477cdf0e10cSrcweir Point aPos; 478cdf0e10cSrcweir sal_GlyphId aGlyphId; 479cdf0e10cSrcweir for( int nStart = 0; rLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart ); ) 480cdf0e10cSrcweir { 481cdf0e10cSrcweir cairo_glyph_t aGlyph; 482cdf0e10cSrcweir aGlyph.index = aGlyphId & GF_IDXMASK; 483cdf0e10cSrcweir aGlyph.x = aPos.X(); 484cdf0e10cSrcweir aGlyph.y = aPos.Y(); 485cdf0e10cSrcweir cairo_glyphs.push_back(aGlyph); 486cdf0e10cSrcweir } 487cdf0e10cSrcweir 488cdf0e10cSrcweir if (cairo_glyphs.empty()) 489cdf0e10cSrcweir return; 490cdf0e10cSrcweir 491cdf0e10cSrcweir // find a XRenderPictFormat compatible with the Drawable 492cdf0e10cSrcweir XRenderPictFormat* pVisualFormat = static_cast<XRenderPictFormat*>(GetXRenderFormat()); 493cdf0e10cSrcweir if( !pVisualFormat ) 494cdf0e10cSrcweir { 495cdf0e10cSrcweir Visual* pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual(); 496cdf0e10cSrcweir pVisualFormat = XRenderPeer::GetInstance().FindVisualFormat( pVisual ); 497cdf0e10cSrcweir // cache the XRenderPictFormat 498cdf0e10cSrcweir SetXRenderFormat( static_cast<void*>(pVisualFormat) ); 499cdf0e10cSrcweir } 500cdf0e10cSrcweir 501cdf0e10cSrcweir DBG_ASSERT( pVisualFormat!=NULL, "no matching XRenderPictFormat for text" ); 502cdf0e10cSrcweir if( !pVisualFormat ) 503cdf0e10cSrcweir return; 504cdf0e10cSrcweir 505cdf0e10cSrcweir CairoWrapper &rCairo = CairoWrapper::get(); 506cdf0e10cSrcweir 507cdf0e10cSrcweir Display* pDisplay = GetXDisplay(); 508cdf0e10cSrcweir 509cdf0e10cSrcweir cairo_surface_t *surface = rCairo.xlib_surface_create_with_xrender_format (pDisplay, 510cdf0e10cSrcweir hDrawable_, ScreenOfDisplay(pDisplay, m_nScreen), pVisualFormat, SAL_MAX_INT16, SAL_MAX_INT16); 511cdf0e10cSrcweir 512cdf0e10cSrcweir /* 513cdf0e10cSrcweir * It might be ideal to cache surface and cairo context between calls and 514cdf0e10cSrcweir * only destroy it when the drawable changes, but to do that we need to at 515cdf0e10cSrcweir * least change the SalFrame etc impls to dtor the SalGraphics *before* the 516cdf0e10cSrcweir * destruction of the windows they reference 517cdf0e10cSrcweir */ 518cdf0e10cSrcweir cairo_t *cr = rCairo.create(surface); 519cdf0e10cSrcweir rCairo.surface_destroy(surface); 520cdf0e10cSrcweir 521cdf0e10cSrcweir if (const void *pOptions = Application::GetSettings().GetStyleSettings().GetCairoFontOptions()) 522cdf0e10cSrcweir rCairo.set_font_options( cr, pOptions); 523cdf0e10cSrcweir 524cdf0e10cSrcweir if( mpClipRegion && !XEmptyRegion( mpClipRegion ) ) 525cdf0e10cSrcweir { 526cdf0e10cSrcweir for (long i = 0; i < mpClipRegion->numRects; ++i) 527cdf0e10cSrcweir { 528cdf0e10cSrcweir rCairo.rectangle(cr, 529cdf0e10cSrcweir mpClipRegion->rects[i].x1, 530cdf0e10cSrcweir mpClipRegion->rects[i].y1, 531cdf0e10cSrcweir mpClipRegion->rects[i].x2 - mpClipRegion->rects[i].x1, 532cdf0e10cSrcweir mpClipRegion->rects[i].y2 - mpClipRegion->rects[i].y1); 533cdf0e10cSrcweir } 534cdf0e10cSrcweir rCairo.clip(cr); 535cdf0e10cSrcweir } 536cdf0e10cSrcweir 537cdf0e10cSrcweir rCairo.set_source_rgb(cr, 538cdf0e10cSrcweir SALCOLOR_RED(nTextColor_)/255.0, 539cdf0e10cSrcweir SALCOLOR_GREEN(nTextColor_)/255.0, 540cdf0e10cSrcweir SALCOLOR_BLUE(nTextColor_)/255.0); 541cdf0e10cSrcweir 542cdf0e10cSrcweir ServerFont& rFont = rLayout.GetServerFont(); 543cdf0e10cSrcweir 544cdf0e10cSrcweir cairo_font_face_t* font_face = NULL; 545cdf0e10cSrcweir 546cdf0e10cSrcweir void *pId = rFont.GetFtFace(); 547cdf0e10cSrcweir font_face = (cairo_font_face_t*)m_aCairoFontsCache.FindCachedFont(pId); 548cdf0e10cSrcweir if (!font_face) 549cdf0e10cSrcweir { 550cdf0e10cSrcweir font_face = rCairo.ft_font_face_create_for_ft_face(pId, rFont.GetLoadFlags()); 551cdf0e10cSrcweir m_aCairoFontsCache.CacheFont(font_face, pId); 552cdf0e10cSrcweir } 553cdf0e10cSrcweir 554cdf0e10cSrcweir rCairo.set_font_face(cr, font_face); 555cdf0e10cSrcweir 556cdf0e10cSrcweir cairo_matrix_t m; 557cdf0e10cSrcweir const ImplFontSelectData& rFSD = rFont.GetFontSelData(); 558cdf0e10cSrcweir int nWidth = rFSD.mnWidth ? rFSD.mnWidth : rFSD.mnHeight; 559cdf0e10cSrcweir 560cdf0e10cSrcweir rCairo.matrix_init_identity(&m); 561cdf0e10cSrcweir 562cdf0e10cSrcweir if (rLayout.GetOrientation()) 563cdf0e10cSrcweir rCairo.matrix_rotate(&m, (3600 - rLayout.GetOrientation()) * M_PI / 1800.0); 564cdf0e10cSrcweir 565cdf0e10cSrcweir rCairo.matrix_scale(&m, nWidth, rFSD.mnHeight); 566cdf0e10cSrcweir if (rFont.NeedsArtificialItalic()) 567cdf0e10cSrcweir m.xy = -m.xx * 0x6000L / 0x10000L; 568cdf0e10cSrcweir 569cdf0e10cSrcweir rCairo.set_font_matrix(cr, &m); 570cdf0e10cSrcweir rCairo.show_glyphs(cr, &cairo_glyphs[0], cairo_glyphs.size()); 571cdf0e10cSrcweir rCairo.destroy(cr); 572cdf0e10cSrcweir } 573cdf0e10cSrcweir 574cdf0e10cSrcweir //-------------------------------------------------------------------------- 575cdf0e10cSrcweir 576cdf0e10cSrcweir void X11SalGraphics::DrawServerAAFontString( const ServerFontLayout& rLayout ) 577cdf0e10cSrcweir { 578cdf0e10cSrcweir // get xrender target for this drawable 579cdf0e10cSrcweir Picture aDstPic = GetXRenderPicture(); 580cdf0e10cSrcweir if( !aDstPic ) 581cdf0e10cSrcweir return; 582cdf0e10cSrcweir 583cdf0e10cSrcweir // get a XRenderPicture for the font foreground 584cdf0e10cSrcweir // TODO: move into own method 585cdf0e10cSrcweir XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); 586cdf0e10cSrcweir XRenderPictFormat* pVisualFormat = (XRenderPictFormat*)GetXRenderFormat(); 587cdf0e10cSrcweir DBG_ASSERT( pVisualFormat, "we already have a render picture, but XRenderPictFormat==NULL???"); 588cdf0e10cSrcweir const int nVisualDepth = pVisualFormat->depth; 589cdf0e10cSrcweir SalDisplay::RenderEntry& rEntry = GetDisplay()->GetRenderEntries( m_nScreen )[ nVisualDepth ]; 590cdf0e10cSrcweir if( !rEntry.m_aPicture ) 591cdf0e10cSrcweir { 592cdf0e10cSrcweir // create and cache XRenderPicture for the font foreground 593cdf0e10cSrcweir Display* pDisplay = GetXDisplay(); 594cdf0e10cSrcweir #ifdef DEBUG 595cdf0e10cSrcweir int iDummy; 596cdf0e10cSrcweir unsigned uDummy; 597cdf0e10cSrcweir XLIB_Window wDummy; 598cdf0e10cSrcweir unsigned int nDrawDepth; 599cdf0e10cSrcweir ::XGetGeometry( pDisplay, hDrawable_, &wDummy, &iDummy, &iDummy, 600cdf0e10cSrcweir &uDummy, &uDummy, &uDummy, &nDrawDepth ); 601cdf0e10cSrcweir DBG_ASSERT( static_cast<unsigned>(nVisualDepth) == nDrawDepth, "depth messed up for XRender" ); 602cdf0e10cSrcweir #endif 603cdf0e10cSrcweir 604cdf0e10cSrcweir rEntry.m_aPixmap = ::XCreatePixmap( pDisplay, hDrawable_, 1, 1, nVisualDepth ); 605cdf0e10cSrcweir 606cdf0e10cSrcweir XRenderPictureAttributes aAttr; 607cdf0e10cSrcweir aAttr.repeat = true; 608cdf0e10cSrcweir rEntry.m_aPicture = rRenderPeer.CreatePicture ( rEntry.m_aPixmap, pVisualFormat, CPRepeat, &aAttr ); 609cdf0e10cSrcweir } 610cdf0e10cSrcweir 611cdf0e10cSrcweir // set font foreground color and opacity 612cdf0e10cSrcweir XRenderColor aRenderColor = GetXRenderColor( nTextColor_ ); 613cdf0e10cSrcweir rRenderPeer.FillRectangle( PictOpSrc, rEntry.m_aPicture, &aRenderColor, 0, 0, 1, 1 ); 614cdf0e10cSrcweir 615cdf0e10cSrcweir // set clipping 616cdf0e10cSrcweir // TODO: move into GetXRenderPicture()? 617cdf0e10cSrcweir if( mpClipRegion && !XEmptyRegion( mpClipRegion ) ) 618cdf0e10cSrcweir rRenderPeer.SetPictureClipRegion( aDstPic, mpClipRegion ); 619cdf0e10cSrcweir 620cdf0e10cSrcweir ServerFont& rFont = rLayout.GetServerFont(); 621cdf0e10cSrcweir X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer(); 622cdf0e10cSrcweir GlyphSet aGlyphSet = rGlyphPeer.GetGlyphSet( rFont, m_nScreen ); 623cdf0e10cSrcweir 624cdf0e10cSrcweir Point aPos; 625cdf0e10cSrcweir static const int MAXGLYPHS = 160; 626cdf0e10cSrcweir sal_GlyphId aGlyphAry[ MAXGLYPHS ]; 627cdf0e10cSrcweir int nMaxGlyphs = rLayout.GetOrientation() ? 1 : MAXGLYPHS; 628cdf0e10cSrcweir for( int nStart = 0;;) 629cdf0e10cSrcweir { 630cdf0e10cSrcweir int nGlyphs = rLayout.GetNextGlyphs( nMaxGlyphs, aGlyphAry, aPos, nStart ); 631cdf0e10cSrcweir if( !nGlyphs ) 632cdf0e10cSrcweir break; 633cdf0e10cSrcweir 634cdf0e10cSrcweir // #i51924# avoid 32->16bit coordinate truncation problem in X11 635cdf0e10cSrcweir // TODO: reevaluate once displays with >30000 pixels are available 636cdf0e10cSrcweir if( aPos.X() >= 30000 || aPos.Y() >= 30000 ) 637cdf0e10cSrcweir continue; 638cdf0e10cSrcweir 639cdf0e10cSrcweir unsigned int aRenderAry[ MAXGLYPHS ]; 640cdf0e10cSrcweir for( int i = 0; i < nGlyphs; ++i ) 641cdf0e10cSrcweir aRenderAry[ i ] = rGlyphPeer.GetGlyphId( rFont, aGlyphAry[i] ); 642cdf0e10cSrcweir rRenderPeer.CompositeString32( rEntry.m_aPicture, aDstPic, 643cdf0e10cSrcweir aGlyphSet, aPos.X(), aPos.Y(), aRenderAry, nGlyphs ); 644cdf0e10cSrcweir } 645cdf0e10cSrcweir } 646cdf0e10cSrcweir 647cdf0e10cSrcweir //-------------------------------------------------------------------------- 648cdf0e10cSrcweir 649cdf0e10cSrcweir bool X11SalGraphics::DrawServerAAForcedString( const ServerFontLayout& rLayout ) 650cdf0e10cSrcweir { 651cdf0e10cSrcweir ServerFont& rFont = rLayout.GetServerFont(); 652cdf0e10cSrcweir 653cdf0e10cSrcweir // prepare glyphs and get extent of operation 654cdf0e10cSrcweir X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer(); 655cdf0e10cSrcweir int nXmin = 0; 656cdf0e10cSrcweir int nXmax = 0; 657cdf0e10cSrcweir int nYmin = 0; 658cdf0e10cSrcweir int nYmax = 0; 659cdf0e10cSrcweir int nStart = 0; 660cdf0e10cSrcweir Point aPos; 661cdf0e10cSrcweir sal_GlyphId nGlyph; 662cdf0e10cSrcweir for( bool bFirst=true; rLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart ); ) 663cdf0e10cSrcweir { 664cdf0e10cSrcweir const RawBitmap* const pRawBitmap = rGlyphPeer.GetRawBitmap( rFont, nGlyph ); 665cdf0e10cSrcweir if( !pRawBitmap ) 666cdf0e10cSrcweir continue; 667cdf0e10cSrcweir 668cdf0e10cSrcweir const int nX1 = aPos.X() + pRawBitmap->mnXOffset; 669cdf0e10cSrcweir const int nY1 = aPos.Y() + pRawBitmap->mnYOffset; 670cdf0e10cSrcweir const int nX2 = nX1 + pRawBitmap->mnWidth; 671cdf0e10cSrcweir const int nY2 = nY1 + pRawBitmap->mnHeight; 672cdf0e10cSrcweir 673cdf0e10cSrcweir if( bFirst ) 674cdf0e10cSrcweir { 675cdf0e10cSrcweir bFirst = false; 676cdf0e10cSrcweir nXmin = nX1; 677cdf0e10cSrcweir nXmax = nX2; 678cdf0e10cSrcweir nYmin = nY1; 679cdf0e10cSrcweir nYmax = nY2; 680cdf0e10cSrcweir } 681cdf0e10cSrcweir else 682cdf0e10cSrcweir { 683cdf0e10cSrcweir if( nXmin > nX1 ) nXmin = nX1; 684cdf0e10cSrcweir if( nXmax < nX2 ) nXmax = nX2; 685cdf0e10cSrcweir if( nYmin > nY1 ) nYmin = nY1; 686cdf0e10cSrcweir if( nYmax < nY2 ) nYmax = nY2; 687cdf0e10cSrcweir } 688cdf0e10cSrcweir } 689cdf0e10cSrcweir 690cdf0e10cSrcweir // get XImage 691cdf0e10cSrcweir GetDisplay()->GetXLib()->PushXErrorLevel( true ); 692cdf0e10cSrcweir Display* pDisplay = GetXDisplay(); 693cdf0e10cSrcweir 694cdf0e10cSrcweir XRectangle aXRect; 695cdf0e10cSrcweir long nWidth = 1, nHeight = 1; 696cdf0e10cSrcweir if( m_pFrame ) 697cdf0e10cSrcweir nWidth = m_pFrame->maGeometry.nWidth, nHeight = m_pFrame->maGeometry.nHeight; 698cdf0e10cSrcweir else if( m_pVDev ) 699cdf0e10cSrcweir nWidth = m_pVDev->GetWidth(), nHeight = m_pVDev->GetHeight(); 700cdf0e10cSrcweir 701cdf0e10cSrcweir if( mpClipRegion && !XEmptyRegion( mpClipRegion ) ) 702cdf0e10cSrcweir { 703cdf0e10cSrcweir // get bounding box 704cdf0e10cSrcweir XClipBox( mpClipRegion, &aXRect ); 705cdf0e10cSrcweir // clip with window 706cdf0e10cSrcweir if( aXRect.x < 0 ) aXRect.x = 0; 707cdf0e10cSrcweir 708cdf0e10cSrcweir if( aXRect.y < 0 ) aXRect.y = 0; 709cdf0e10cSrcweir if( aXRect.width+aXRect.x > nWidth ) aXRect.width = nWidth-aXRect.x; 710cdf0e10cSrcweir if( aXRect.height+aXRect.y > nHeight ) aXRect.height = nHeight-aXRect.y; 711cdf0e10cSrcweir } 712cdf0e10cSrcweir else 713cdf0e10cSrcweir { 714cdf0e10cSrcweir aXRect.x = 0; 715cdf0e10cSrcweir aXRect.y = 0; 716cdf0e10cSrcweir aXRect.width = nWidth; 717cdf0e10cSrcweir aXRect.height = nHeight; 718cdf0e10cSrcweir } 719cdf0e10cSrcweir if( m_pFrame ) 720cdf0e10cSrcweir { 721cdf0e10cSrcweir // clip with screen 722cdf0e10cSrcweir int nScreenX = m_pFrame->maGeometry.nX+aXRect.x; 723cdf0e10cSrcweir int nScreenY = m_pFrame->maGeometry.nY+aXRect.y; 724cdf0e10cSrcweir const Size& rScreenSize = GetDisplay()->getDataForScreen( m_nScreen ).m_aSize; 725cdf0e10cSrcweir int nScreenW = rScreenSize.Width(); 726cdf0e10cSrcweir int nScreenH = rScreenSize.Height(); 727cdf0e10cSrcweir if( nScreenX < 0 ) 728cdf0e10cSrcweir aXRect.x -= nScreenX, aXRect.width += nScreenX; 729cdf0e10cSrcweir if( nScreenX+aXRect.width > nScreenW ) 730cdf0e10cSrcweir aXRect.width = nScreenW-nScreenX; 731cdf0e10cSrcweir if( nScreenY < 0 ) 732cdf0e10cSrcweir aXRect.y -= nScreenY, aXRect.height += nScreenY; 733cdf0e10cSrcweir if( nScreenY+aXRect.height > nScreenH ) 734cdf0e10cSrcweir aXRect.height = nScreenH-nScreenY; 735cdf0e10cSrcweir } 736cdf0e10cSrcweir 737cdf0e10cSrcweir 738cdf0e10cSrcweir if( nXmin < aXRect.x ) nXmin = aXRect.x; 739cdf0e10cSrcweir if( nYmin < aXRect.y ) nYmin = aXRect.y; 740cdf0e10cSrcweir if( nXmax >= aXRect.x+aXRect.width ) nXmax = aXRect.x + aXRect.width - 1; 741cdf0e10cSrcweir if( nYmax >= aXRect.y+aXRect.height ) nYmax = aXRect.y + aXRect.height - 1; 742cdf0e10cSrcweir 743cdf0e10cSrcweir if( nXmin > nXmax ) 744cdf0e10cSrcweir return false; 745cdf0e10cSrcweir if( nYmin > nYmax ) 746cdf0e10cSrcweir return false; 747cdf0e10cSrcweir 748cdf0e10cSrcweir XImage* pImg = XGetImage( pDisplay, hDrawable_, 749cdf0e10cSrcweir nXmin, nYmin, 750cdf0e10cSrcweir (nXmax-nXmin+1), (nYmax-nYmin+1), 751cdf0e10cSrcweir ~0, ZPixmap ); 752cdf0e10cSrcweir if( pImg == NULL ) 753cdf0e10cSrcweir { 754cdf0e10cSrcweir if( m_pFrame ) 755cdf0e10cSrcweir { 756cdf0e10cSrcweir // the reason we did not get an image could be that the frame 757cdf0e10cSrcweir // geometry changed in the meantime; lets get the current geometry 758cdf0e10cSrcweir // and clip against the current window size as well as the screen 759cdf0e10cSrcweir // with the current frame position 760cdf0e10cSrcweir const Size& rScreenSize = GetDisplay()->getDataForScreen(m_nScreen).m_aSize; 761cdf0e10cSrcweir int nScreenW = rScreenSize.Width(); 762cdf0e10cSrcweir int nScreenH = rScreenSize.Height(); 763cdf0e10cSrcweir XLIB_Window aRoot = None; 764cdf0e10cSrcweir int x = 0, y = 0; 765cdf0e10cSrcweir unsigned int w = 0, h = 0, bw = 0, d; 766cdf0e10cSrcweir XGetGeometry( pDisplay, hDrawable_, &aRoot, &x, &y, &w, &h, &bw, &d ); 767cdf0e10cSrcweir XTranslateCoordinates( pDisplay, hDrawable_, aRoot, 0, 0, &x, &y, &aRoot ); 768cdf0e10cSrcweir if( nXmin + x < 0 ) // clip on left screen edge 769cdf0e10cSrcweir nXmin += x-nXmin; 770cdf0e10cSrcweir if( nYmin + y < 0 ) // clip on top screen edge 771cdf0e10cSrcweir nYmin += y-nYmin; 772cdf0e10cSrcweir if( nXmax >= int(w) ) // clip on right window egde 773cdf0e10cSrcweir nXmax = w-1; 774cdf0e10cSrcweir if( nYmax >= int(h) ) // clip on bottom window edge 775cdf0e10cSrcweir nYmax = h-1; 776cdf0e10cSrcweir if( nXmax + x >= nScreenW ) // clip on right screen edge 777cdf0e10cSrcweir nXmax -= (nXmax + x - nScreenW)+1; 778cdf0e10cSrcweir if( nYmax + y >= nScreenH ) // clip on bottom screen edge 779cdf0e10cSrcweir nYmax -= (nYmax + y - nScreenH)+1; 780cdf0e10cSrcweir if( nXmax >= nXmin && nYmax >= nYmin ) 781cdf0e10cSrcweir { 782cdf0e10cSrcweir // try again to get the image 783cdf0e10cSrcweir pImg = XGetImage( pDisplay, hDrawable_, 784cdf0e10cSrcweir nXmin, nYmin, 785cdf0e10cSrcweir (nXmax-nXmin+1), (nYmax-nYmin+1), 786cdf0e10cSrcweir ~0, ZPixmap ); 787cdf0e10cSrcweir } 788cdf0e10cSrcweir } 789cdf0e10cSrcweir if( pImg == NULL ) 790cdf0e10cSrcweir { 791cdf0e10cSrcweir GetDisplay()->GetXLib()->PopXErrorLevel(); 792cdf0e10cSrcweir return false; 793cdf0e10cSrcweir } 794cdf0e10cSrcweir } 795cdf0e10cSrcweir 796cdf0e10cSrcweir // prepare context 797cdf0e10cSrcweir GC nGC = GetFontGC(); 798cdf0e10cSrcweir XGCValues aGCVal; 799cdf0e10cSrcweir XGetGCValues( pDisplay, nGC, GCForeground, &aGCVal ); 800cdf0e10cSrcweir 801cdf0e10cSrcweir unsigned long nOrigColor = XGetPixel( pImg, 0, 0 ); 802cdf0e10cSrcweir XPutPixel( pImg, 0, 0, aGCVal.foreground ); 803cdf0e10cSrcweir unsigned char aColor[4]; 804cdf0e10cSrcweir aColor[0] = pImg->data[0]; 805cdf0e10cSrcweir aColor[1] = pImg->data[1]; 806cdf0e10cSrcweir aColor[2] = pImg->data[2]; 807cdf0e10cSrcweir aColor[3] = pImg->data[3]; 808cdf0e10cSrcweir XPutPixel( pImg, 0, 0, nOrigColor ); 809cdf0e10cSrcweir 810cdf0e10cSrcweir // work on XImage 811cdf0e10cSrcweir const int bpp = pImg->bits_per_pixel >> 3; 812cdf0e10cSrcweir for( nStart = 0; rLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart ); ) 813cdf0e10cSrcweir { 814cdf0e10cSrcweir const RawBitmap* const pRawBitmap = rGlyphPeer.GetRawBitmap( rFont, nGlyph ); 815cdf0e10cSrcweir if( !pRawBitmap ) 816cdf0e10cSrcweir continue; 817cdf0e10cSrcweir 818cdf0e10cSrcweir const int nX1 = aPos.X() + pRawBitmap->mnXOffset; 819cdf0e10cSrcweir const int nY1 = aPos.Y() + pRawBitmap->mnYOffset; 820cdf0e10cSrcweir 821cdf0e10cSrcweir if( (nX1 <= nXmax) && (int(nX1 + pRawBitmap->mnWidth) > nXmin) 822cdf0e10cSrcweir && (nY1 <= nYmax) && (int(nY1 + pRawBitmap->mnHeight) > nYmin) ) 823cdf0e10cSrcweir { 824cdf0e10cSrcweir const unsigned char* p10 = pRawBitmap->mpBits; 825cdf0e10cSrcweir unsigned char* p20 = (unsigned char*)pImg->data; // dest left limit 826cdf0e10cSrcweir p20 += (nY1 - nYmin) * pImg->bytes_per_line; 827cdf0e10cSrcweir unsigned char* p21 = p20 + (nX1 - nXmin + pImg->xoffset) * bpp; 828cdf0e10cSrcweir int y = pRawBitmap->mnHeight; 829cdf0e10cSrcweir if( y > nYmax - nY1 ) 830cdf0e10cSrcweir y = nYmax - nY1 + 1; 831cdf0e10cSrcweir while( --y >= 0 ) 832cdf0e10cSrcweir { 833cdf0e10cSrcweir if( p20 >= (unsigned char*)pImg->data ) 834cdf0e10cSrcweir { 835cdf0e10cSrcweir unsigned char* const p22 = p20 + pImg->width * bpp; // dest right limit 836cdf0e10cSrcweir unsigned char* pDst = p21; 837cdf0e10cSrcweir const unsigned char* pSrc = p10; 838cdf0e10cSrcweir for( int x = pRawBitmap->mnWidth; (--x >= 0) && (p22 > pDst); ++pSrc ) 839cdf0e10cSrcweir { 840cdf0e10cSrcweir if( (*pSrc == 0) || (p20 > pDst) ) // keep background 841cdf0e10cSrcweir pDst += bpp; 842cdf0e10cSrcweir else if( *pSrc == 0xFF ) // paint foreground 843cdf0e10cSrcweir { 844cdf0e10cSrcweir const unsigned char* pColor = aColor; 845cdf0e10cSrcweir for( int z = bpp; --z >= 0; ++pColor, ++pDst ) 846cdf0e10cSrcweir *pDst = *pColor; 847cdf0e10cSrcweir } 848cdf0e10cSrcweir else // blend fg into bg 849cdf0e10cSrcweir { 850cdf0e10cSrcweir const unsigned char* pColor = aColor; 851cdf0e10cSrcweir for( int z = bpp; --z >= 0; ++pColor, ++pDst ) 852cdf0e10cSrcweir // theoretically it should be *257) >> 16 853cdf0e10cSrcweir // but the error is <0.4% worst case and we are in 854cdf0e10cSrcweir // the innermost loop of very perf-sensitive code 855cdf0e10cSrcweir 856cdf0e10cSrcweir *pDst += (*pSrc * ((int)*pColor - *pDst)) >> 8; 857cdf0e10cSrcweir } 858cdf0e10cSrcweir } 859cdf0e10cSrcweir } 860cdf0e10cSrcweir p10 += pRawBitmap->mnScanlineSize; 861cdf0e10cSrcweir p20 += pImg->bytes_per_line; 862cdf0e10cSrcweir p21 += pImg->bytes_per_line; 863cdf0e10cSrcweir } 864cdf0e10cSrcweir } 865cdf0e10cSrcweir } 866cdf0e10cSrcweir 867cdf0e10cSrcweir // put XImage 868cdf0e10cSrcweir XPutImage( pDisplay, hDrawable_, nGC, pImg, 869cdf0e10cSrcweir 0, 0, nXmin, nYmin, (nXmax - nXmin + 1), (nYmax - nYmin + 1) ); 870cdf0e10cSrcweir XDestroyImage( pImg ); 871cdf0e10cSrcweir 872cdf0e10cSrcweir GetDisplay()->GetXLib()->PopXErrorLevel(); 873cdf0e10cSrcweir return true; 874cdf0e10cSrcweir } 875cdf0e10cSrcweir 876cdf0e10cSrcweir //-------------------------------------------------------------------------- 877cdf0e10cSrcweir 878cdf0e10cSrcweir void X11SalGraphics::DrawServerSimpleFontString( const ServerFontLayout& rSalLayout ) 879cdf0e10cSrcweir { 880cdf0e10cSrcweir ServerFont& rFont = rSalLayout.GetServerFont(); 881cdf0e10cSrcweir X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer(); 882cdf0e10cSrcweir 883cdf0e10cSrcweir Display* pDisplay = GetXDisplay(); 884cdf0e10cSrcweir GC nGC = GetFontGC(); 885cdf0e10cSrcweir 886cdf0e10cSrcweir XGCValues aGCVal; 887cdf0e10cSrcweir aGCVal.fill_style = FillStippled; 888cdf0e10cSrcweir aGCVal.line_width = 0; 889cdf0e10cSrcweir GC tmpGC = XCreateGC( pDisplay, hDrawable_, GCFillStyle|GCLineWidth, &aGCVal ); 890cdf0e10cSrcweir XCopyGC( pDisplay, nGC, (1<<GCLastBit)-(1+GCFillStyle+GCLineWidth), tmpGC ); 891cdf0e10cSrcweir 892cdf0e10cSrcweir Point aPos; 893cdf0e10cSrcweir sal_GlyphId nGlyph; 894cdf0e10cSrcweir for( int nStart = 0; rSalLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart ); ) 895cdf0e10cSrcweir { 896cdf0e10cSrcweir // #i51924# avoid 32->16bit coordinate truncation problem in X11 897cdf0e10cSrcweir // TODO: reevaluate once displays with >30000 pixels are available 898cdf0e10cSrcweir if( aPos.X() >= 30000 || aPos.Y() >= 30000 ) 899cdf0e10cSrcweir continue; 900cdf0e10cSrcweir 901cdf0e10cSrcweir Pixmap aStipple = rGlyphPeer.GetPixmap( rFont, nGlyph, m_nScreen ); 902cdf0e10cSrcweir const GlyphMetric& rGM = rFont.GetGlyphMetric( nGlyph ); 903cdf0e10cSrcweir 904cdf0e10cSrcweir if( aStipple != None ) 905cdf0e10cSrcweir { 906cdf0e10cSrcweir const int nDestX = aPos.X() + rGM.GetOffset().X(); 907cdf0e10cSrcweir const int nDestY = aPos.Y() + rGM.GetOffset().Y(); 908cdf0e10cSrcweir 909cdf0e10cSrcweir aGCVal.stipple = aStipple; 910cdf0e10cSrcweir aGCVal.ts_x_origin = nDestX; 911cdf0e10cSrcweir aGCVal.ts_y_origin = nDestY; 912cdf0e10cSrcweir XChangeGC( pDisplay, tmpGC, GCStipple|GCTileStipXOrigin|GCTileStipYOrigin, &aGCVal ); 913cdf0e10cSrcweir 914cdf0e10cSrcweir const int nWidth = rGM.GetSize().Width(); 915cdf0e10cSrcweir const int nHeight = rGM.GetSize().Height(); 916cdf0e10cSrcweir XFillRectangle( pDisplay, hDrawable_, tmpGC, nDestX, nDestY, nWidth, nHeight ); 917cdf0e10cSrcweir } 918cdf0e10cSrcweir } 919cdf0e10cSrcweir 920cdf0e10cSrcweir XFreeGC( pDisplay, tmpGC ); 921cdf0e10cSrcweir } 922cdf0e10cSrcweir 923cdf0e10cSrcweir //-------------------------------------------------------------------------- 924cdf0e10cSrcweir 925cdf0e10cSrcweir void X11SalGraphics::DrawServerFontLayout( const ServerFontLayout& rLayout ) 926cdf0e10cSrcweir { 927cdf0e10cSrcweir // draw complex text 928cdf0e10cSrcweir ServerFont& rFont = rLayout.GetServerFont(); 929cdf0e10cSrcweir const bool bVertical = rFont.GetFontSelData().mbVertical; 930cdf0e10cSrcweir 931cdf0e10cSrcweir if( !bVertical && CairoWrapper::get().isCairoRenderable(rFont) ) 932cdf0e10cSrcweir DrawCairoAAFontString( rLayout ); 933cdf0e10cSrcweir else 934cdf0e10cSrcweir { 935cdf0e10cSrcweir X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer(); 936cdf0e10cSrcweir if( rGlyphPeer.GetGlyphSet( rFont, m_nScreen ) ) 937cdf0e10cSrcweir DrawServerAAFontString( rLayout ); 938cdf0e10cSrcweir else if( !rGlyphPeer.ForcedAntialiasing( rFont, m_nScreen ) ) 939cdf0e10cSrcweir DrawServerSimpleFontString( rLayout ); 940cdf0e10cSrcweir else 941cdf0e10cSrcweir DrawServerAAForcedString( rLayout ); 942cdf0e10cSrcweir } 943cdf0e10cSrcweir } 944cdf0e10cSrcweir 945cdf0e10cSrcweir //-------------------------------------------------------------------------- 946cdf0e10cSrcweir 947cdf0e10cSrcweir const ImplFontCharMap* X11SalGraphics::GetImplFontCharMap() const 948cdf0e10cSrcweir { 949cdf0e10cSrcweir if( !mpServerFont[0] ) 950cdf0e10cSrcweir return NULL; 951cdf0e10cSrcweir 952cdf0e10cSrcweir const ImplFontCharMap* pIFCMap = mpServerFont[0]->GetImplFontCharMap(); 953cdf0e10cSrcweir return pIFCMap; 954cdf0e10cSrcweir } 955cdf0e10cSrcweir 956cdf0e10cSrcweir // ---------------------------------------------------------------------------- 957cdf0e10cSrcweir // 958cdf0e10cSrcweir // SalGraphics 959cdf0e10cSrcweir // 960cdf0e10cSrcweir // ---------------------------------------------------------------------------- 961cdf0e10cSrcweir 962cdf0e10cSrcweir sal_uInt16 X11SalGraphics::SetFont( ImplFontSelectData *pEntry, int nFallbackLevel ) 963cdf0e10cSrcweir { 964cdf0e10cSrcweir sal_uInt16 nRetVal = 0; 965cdf0e10cSrcweir if( !setFont( pEntry, nFallbackLevel ) ) 966cdf0e10cSrcweir nRetVal |= SAL_SETFONT_BADFONT; 967cdf0e10cSrcweir if( bPrinter_ || (mpServerFont[ nFallbackLevel ] != NULL) ) 968cdf0e10cSrcweir nRetVal |= SAL_SETFONT_USEDRAWTEXTARRAY; 969cdf0e10cSrcweir return nRetVal; 970cdf0e10cSrcweir } 971cdf0e10cSrcweir 972cdf0e10cSrcweir // ---------------------------------------------------------------------------- 973cdf0e10cSrcweir 974cdf0e10cSrcweir void 975cdf0e10cSrcweir X11SalGraphics::SetTextColor( SalColor nSalColor ) 976cdf0e10cSrcweir { 977cdf0e10cSrcweir if( nTextColor_ != nSalColor ) 978cdf0e10cSrcweir { 979cdf0e10cSrcweir nTextColor_ = nSalColor; 980cdf0e10cSrcweir nTextPixel_ = GetPixel( nSalColor ); 981cdf0e10cSrcweir bFontGC_ = sal_False; 982cdf0e10cSrcweir } 983cdf0e10cSrcweir } 984cdf0e10cSrcweir 985cdf0e10cSrcweir // ---------------------------------------------------------------------------- 986cdf0e10cSrcweir 987cdf0e10cSrcweir bool X11SalGraphics::AddTempDevFont( ImplDevFontList* pFontList, 988cdf0e10cSrcweir const String& rFileURL, const String& rFontName ) 989cdf0e10cSrcweir { 990cdf0e10cSrcweir // inform PSP font manager 991cdf0e10cSrcweir rtl::OUString aUSystemPath; 992cdf0e10cSrcweir OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFileURL, aUSystemPath ) ); 993cdf0e10cSrcweir rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); 994cdf0e10cSrcweir OString aOFileName( OUStringToOString( aUSystemPath, aEncoding ) ); 995cdf0e10cSrcweir psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); 996cdf0e10cSrcweir int nFontId = rMgr.addFontFile( aOFileName, 0 ); 997cdf0e10cSrcweir if( !nFontId ) 998cdf0e10cSrcweir return false; 999cdf0e10cSrcweir 1000cdf0e10cSrcweir // prepare font data 1001cdf0e10cSrcweir psp::FastPrintFontInfo aInfo; 1002cdf0e10cSrcweir rMgr.getFontFastInfo( nFontId, aInfo ); 1003cdf0e10cSrcweir aInfo.m_aFamilyName = rFontName; 1004cdf0e10cSrcweir 1005cdf0e10cSrcweir // inform glyph cache of new font 1006cdf0e10cSrcweir ImplDevFontAttributes aDFA = PspGraphics::Info2DevFontAttributes( aInfo ); 1007cdf0e10cSrcweir aDFA.mnQuality += 5800; 1008cdf0e10cSrcweir 1009cdf0e10cSrcweir int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID ); 1010cdf0e10cSrcweir if( nFaceNum < 0 ) 1011cdf0e10cSrcweir nFaceNum = 0; 1012cdf0e10cSrcweir 1013cdf0e10cSrcweir GlyphCache& rGC = X11GlyphCache::GetInstance(); 1014cdf0e10cSrcweir const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID ); 1015cdf0e10cSrcweir rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA ); 1016cdf0e10cSrcweir 1017cdf0e10cSrcweir // announce new font to device's font list 1018cdf0e10cSrcweir rGC.AnnounceFonts( pFontList ); 1019cdf0e10cSrcweir return true; 1020cdf0e10cSrcweir } 1021cdf0e10cSrcweir 1022cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1023cdf0e10cSrcweir 1024cdf0e10cSrcweir void RegisterFontSubstitutors( ImplDevFontList* ); 1025cdf0e10cSrcweir 1026cdf0e10cSrcweir void X11SalGraphics::GetDevFontList( ImplDevFontList *pList ) 1027cdf0e10cSrcweir { 1028cdf0e10cSrcweir // prepare the GlyphCache using psprint's font infos 1029cdf0e10cSrcweir X11GlyphCache& rGC = X11GlyphCache::GetInstance(); 1030cdf0e10cSrcweir 1031cdf0e10cSrcweir psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); 1032cdf0e10cSrcweir ::std::list< psp::fontID > aList; 1033cdf0e10cSrcweir ::std::list< psp::fontID >::iterator it; 1034cdf0e10cSrcweir psp::FastPrintFontInfo aInfo; 1035cdf0e10cSrcweir rMgr.getFontList( aList ); 1036cdf0e10cSrcweir for( it = aList.begin(); it != aList.end(); ++it ) 1037cdf0e10cSrcweir { 1038cdf0e10cSrcweir if( !rMgr.getFontFastInfo( *it, aInfo ) ) 1039cdf0e10cSrcweir continue; 1040cdf0e10cSrcweir 1041cdf0e10cSrcweir // the GlyphCache must not bother with builtin fonts because 1042cdf0e10cSrcweir // it cannot access or use them anyway 1043cdf0e10cSrcweir if( aInfo.m_eType == psp::fonttype::Builtin ) 1044cdf0e10cSrcweir continue; 1045cdf0e10cSrcweir 1046cdf0e10cSrcweir // normalize face number to the GlyphCache 1047cdf0e10cSrcweir int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID ); 1048cdf0e10cSrcweir if( nFaceNum < 0 ) 1049cdf0e10cSrcweir nFaceNum = 0; 1050cdf0e10cSrcweir 1051cdf0e10cSrcweir // for fonts where extra kerning info can be provided on demand 1052cdf0e10cSrcweir // an ExtraKernInfo object is supplied 1053cdf0e10cSrcweir const ExtraKernInfo* pExtraKernInfo = NULL; 1054cdf0e10cSrcweir if( aInfo.m_eType == psp::fonttype::Type1 ) 1055cdf0e10cSrcweir pExtraKernInfo = new PspKernInfo( *it ); 1056cdf0e10cSrcweir 1057cdf0e10cSrcweir // inform GlyphCache about this font provided by the PsPrint subsystem 1058cdf0e10cSrcweir ImplDevFontAttributes aDFA = PspGraphics::Info2DevFontAttributes( aInfo ); 1059cdf0e10cSrcweir aDFA.mnQuality += 4096; 1060cdf0e10cSrcweir const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID ); 1061cdf0e10cSrcweir rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA, pExtraKernInfo ); 1062cdf0e10cSrcweir } 1063cdf0e10cSrcweir 1064cdf0e10cSrcweir // announce glyphcache fonts 1065cdf0e10cSrcweir rGC.AnnounceFonts( pList ); 1066cdf0e10cSrcweir 1067cdf0e10cSrcweir // register platform specific font substitutions if available 1068cdf0e10cSrcweir if( rMgr.hasFontconfig() ) 1069cdf0e10cSrcweir RegisterFontSubstitutors( pList ); 1070cdf0e10cSrcweir 1071cdf0e10cSrcweir ImplGetSVData()->maGDIData.mbNativeFontConfig = rMgr.hasFontconfig(); 1072cdf0e10cSrcweir } 1073cdf0e10cSrcweir 1074cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1075cdf0e10cSrcweir 1076cdf0e10cSrcweir void X11SalGraphics::GetDevFontSubstList( OutputDevice* ) 1077cdf0e10cSrcweir { 1078cdf0e10cSrcweir // no device specific font substitutions on X11 needed 1079cdf0e10cSrcweir } 1080cdf0e10cSrcweir 1081cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1082cdf0e10cSrcweir 1083cdf0e10cSrcweir void cairosubcallback( void* pPattern ) 1084cdf0e10cSrcweir { 1085cdf0e10cSrcweir CairoWrapper& rCairo = CairoWrapper::get(); 1086cdf0e10cSrcweir if( !rCairo.isValid() ) 1087cdf0e10cSrcweir return; 1088cdf0e10cSrcweir const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 1089cdf0e10cSrcweir const void* pFontOptions = rStyleSettings.GetCairoFontOptions(); 1090cdf0e10cSrcweir if( !pFontOptions ) 1091cdf0e10cSrcweir return; 1092cdf0e10cSrcweir rCairo.ft_font_options_substitute( pFontOptions, pPattern ); 1093cdf0e10cSrcweir } 1094cdf0e10cSrcweir 1095cdf0e10cSrcweir bool GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize, 1096cdf0e10cSrcweir ImplFontOptions& rFontOptions) 1097cdf0e10cSrcweir { 1098cdf0e10cSrcweir // TODO: get rid of these insane enum-conversions 1099cdf0e10cSrcweir // e.g. by using the classic vclenum values inside VCL 1100cdf0e10cSrcweir 1101cdf0e10cSrcweir psp::FastPrintFontInfo aInfo; 1102cdf0e10cSrcweir // set family name 1103cdf0e10cSrcweir aInfo.m_aFamilyName = rFontAttributes.GetFamilyName(); 1104cdf0e10cSrcweir // set italic 1105cdf0e10cSrcweir switch( rFontAttributes.GetSlant() ) 1106cdf0e10cSrcweir { 1107cdf0e10cSrcweir case ITALIC_NONE: 1108cdf0e10cSrcweir aInfo.m_eItalic = psp::italic::Upright; 1109cdf0e10cSrcweir break; 1110cdf0e10cSrcweir case ITALIC_NORMAL: 1111cdf0e10cSrcweir aInfo.m_eItalic = psp::italic::Italic; 1112cdf0e10cSrcweir break; 1113cdf0e10cSrcweir case ITALIC_OBLIQUE: 1114cdf0e10cSrcweir aInfo.m_eItalic = psp::italic::Oblique; 1115cdf0e10cSrcweir break; 1116cdf0e10cSrcweir default: 1117cdf0e10cSrcweir aInfo.m_eItalic = psp::italic::Unknown; 1118cdf0e10cSrcweir break; 1119cdf0e10cSrcweir } 1120cdf0e10cSrcweir // set weight 1121cdf0e10cSrcweir switch( rFontAttributes.GetWeight() ) 1122cdf0e10cSrcweir { 1123cdf0e10cSrcweir case WEIGHT_THIN: 1124cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::Thin; 1125cdf0e10cSrcweir break; 1126cdf0e10cSrcweir case WEIGHT_ULTRALIGHT: 1127cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::UltraLight; 1128cdf0e10cSrcweir break; 1129cdf0e10cSrcweir case WEIGHT_LIGHT: 1130cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::Light; 1131cdf0e10cSrcweir break; 1132cdf0e10cSrcweir case WEIGHT_SEMILIGHT: 1133cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::SemiLight; 1134cdf0e10cSrcweir break; 1135cdf0e10cSrcweir case WEIGHT_NORMAL: 1136cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::Normal; 1137cdf0e10cSrcweir break; 1138cdf0e10cSrcweir case WEIGHT_MEDIUM: 1139cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::Medium; 1140cdf0e10cSrcweir break; 1141cdf0e10cSrcweir case WEIGHT_SEMIBOLD: 1142cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::SemiBold; 1143cdf0e10cSrcweir break; 1144cdf0e10cSrcweir case WEIGHT_BOLD: 1145cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::Bold; 1146cdf0e10cSrcweir break; 1147cdf0e10cSrcweir case WEIGHT_ULTRABOLD: 1148cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::UltraBold; 1149cdf0e10cSrcweir break; 1150cdf0e10cSrcweir case WEIGHT_BLACK: 1151cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::Black; 1152cdf0e10cSrcweir break; 1153cdf0e10cSrcweir default: 1154cdf0e10cSrcweir aInfo.m_eWeight = psp::weight::Unknown; 1155cdf0e10cSrcweir break; 1156cdf0e10cSrcweir } 1157cdf0e10cSrcweir // set width 1158cdf0e10cSrcweir switch( rFontAttributes.GetWidthType() ) 1159cdf0e10cSrcweir { 1160cdf0e10cSrcweir case WIDTH_ULTRA_CONDENSED: 1161cdf0e10cSrcweir aInfo.m_eWidth = psp::width::UltraCondensed; 1162cdf0e10cSrcweir break; 1163cdf0e10cSrcweir case WIDTH_EXTRA_CONDENSED: 1164cdf0e10cSrcweir aInfo.m_eWidth = psp::width::ExtraCondensed; 1165cdf0e10cSrcweir break; 1166cdf0e10cSrcweir case WIDTH_CONDENSED: 1167cdf0e10cSrcweir aInfo.m_eWidth = psp::width::Condensed; 1168cdf0e10cSrcweir break; 1169cdf0e10cSrcweir case WIDTH_SEMI_CONDENSED: 1170cdf0e10cSrcweir aInfo.m_eWidth = psp::width::SemiCondensed; 1171cdf0e10cSrcweir break; 1172cdf0e10cSrcweir case WIDTH_NORMAL: 1173cdf0e10cSrcweir aInfo.m_eWidth = psp::width::Normal; 1174cdf0e10cSrcweir break; 1175cdf0e10cSrcweir case WIDTH_SEMI_EXPANDED: 1176cdf0e10cSrcweir aInfo.m_eWidth = psp::width::SemiExpanded; 1177cdf0e10cSrcweir break; 1178cdf0e10cSrcweir case WIDTH_EXPANDED: 1179cdf0e10cSrcweir aInfo.m_eWidth = psp::width::Expanded; 1180cdf0e10cSrcweir break; 1181cdf0e10cSrcweir case WIDTH_EXTRA_EXPANDED: 1182cdf0e10cSrcweir aInfo.m_eWidth = psp::width::ExtraExpanded; 1183cdf0e10cSrcweir break; 1184cdf0e10cSrcweir case WIDTH_ULTRA_EXPANDED: 1185cdf0e10cSrcweir aInfo.m_eWidth = psp::width::UltraExpanded; 1186cdf0e10cSrcweir break; 1187cdf0e10cSrcweir default: 1188cdf0e10cSrcweir aInfo.m_eWidth = psp::width::Unknown; 1189cdf0e10cSrcweir break; 1190cdf0e10cSrcweir } 1191cdf0e10cSrcweir 1192cdf0e10cSrcweir const psp::PrintFontManager& rPFM = psp::PrintFontManager::get(); 1193cdf0e10cSrcweir bool bOK = rPFM.getFontOptions( aInfo, nSize, cairosubcallback, rFontOptions); 1194cdf0e10cSrcweir return bOK; 1195cdf0e10cSrcweir } 1196cdf0e10cSrcweir 1197cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1198cdf0e10cSrcweir 1199cdf0e10cSrcweir void 1200cdf0e10cSrcweir X11SalGraphics::GetFontMetric( ImplFontMetricData *pMetric, int nFallbackLevel ) 1201cdf0e10cSrcweir { 1202cdf0e10cSrcweir if( nFallbackLevel >= MAX_FALLBACK ) 1203cdf0e10cSrcweir return; 1204cdf0e10cSrcweir 1205cdf0e10cSrcweir if( mpServerFont[nFallbackLevel] != NULL ) 1206cdf0e10cSrcweir { 1207cdf0e10cSrcweir long rDummyFactor; 1208cdf0e10cSrcweir mpServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor ); 1209cdf0e10cSrcweir } 1210cdf0e10cSrcweir } 1211cdf0e10cSrcweir 1212cdf0e10cSrcweir // --------------------------------------------------------------------------- 1213cdf0e10cSrcweir 1214cdf0e10cSrcweir sal_uLong 1215cdf0e10cSrcweir X11SalGraphics::GetKernPairs( sal_uLong nPairs, ImplKernPairData *pKernPairs ) 1216cdf0e10cSrcweir { 1217cdf0e10cSrcweir if( ! bPrinter_ ) 1218cdf0e10cSrcweir { 1219cdf0e10cSrcweir if( mpServerFont[0] != NULL ) 1220cdf0e10cSrcweir { 1221cdf0e10cSrcweir ImplKernPairData* pTmpKernPairs; 1222cdf0e10cSrcweir sal_uLong nGotPairs = mpServerFont[0]->GetKernPairs( &pTmpKernPairs ); 1223cdf0e10cSrcweir for( unsigned int i = 0; i < nPairs && i < nGotPairs; ++i ) 1224cdf0e10cSrcweir pKernPairs[ i ] = pTmpKernPairs[ i ]; 1225cdf0e10cSrcweir delete[] pTmpKernPairs; 1226cdf0e10cSrcweir return nGotPairs; 1227cdf0e10cSrcweir } 1228cdf0e10cSrcweir } 1229cdf0e10cSrcweir return 0; 1230cdf0e10cSrcweir } 1231cdf0e10cSrcweir 1232cdf0e10cSrcweir // --------------------------------------------------------------------------- 1233cdf0e10cSrcweir 1234cdf0e10cSrcweir sal_Bool X11SalGraphics::GetGlyphBoundRect( long nGlyphIndex, Rectangle& rRect ) 1235cdf0e10cSrcweir { 1236cdf0e10cSrcweir int nLevel = nGlyphIndex >> GF_FONTSHIFT; 1237cdf0e10cSrcweir if( nLevel >= MAX_FALLBACK ) 1238cdf0e10cSrcweir return sal_False; 1239cdf0e10cSrcweir 1240cdf0e10cSrcweir ServerFont* pSF = mpServerFont[ nLevel ]; 1241cdf0e10cSrcweir if( !pSF ) 1242cdf0e10cSrcweir return sal_False; 1243cdf0e10cSrcweir 1244cdf0e10cSrcweir nGlyphIndex &= ~GF_FONTMASK; 1245cdf0e10cSrcweir const GlyphMetric& rGM = pSF->GetGlyphMetric( nGlyphIndex ); 1246cdf0e10cSrcweir rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() ); 1247cdf0e10cSrcweir return sal_True; 1248cdf0e10cSrcweir } 1249cdf0e10cSrcweir 1250cdf0e10cSrcweir // --------------------------------------------------------------------------- 1251cdf0e10cSrcweir 1252cdf0e10cSrcweir sal_Bool X11SalGraphics::GetGlyphOutline( long nGlyphIndex, 1253cdf0e10cSrcweir ::basegfx::B2DPolyPolygon& rPolyPoly ) 1254cdf0e10cSrcweir { 1255cdf0e10cSrcweir int nLevel = nGlyphIndex >> GF_FONTSHIFT; 1256cdf0e10cSrcweir if( nLevel >= MAX_FALLBACK ) 1257cdf0e10cSrcweir return sal_False; 1258cdf0e10cSrcweir 1259cdf0e10cSrcweir ServerFont* pSF = mpServerFont[ nLevel ]; 1260cdf0e10cSrcweir if( !pSF ) 1261cdf0e10cSrcweir return sal_False; 1262cdf0e10cSrcweir 1263cdf0e10cSrcweir nGlyphIndex &= ~GF_FONTMASK; 1264cdf0e10cSrcweir if( pSF->GetGlyphOutline( nGlyphIndex, rPolyPoly ) ) 1265cdf0e10cSrcweir return sal_True; 1266cdf0e10cSrcweir 1267cdf0e10cSrcweir return sal_False; 1268cdf0e10cSrcweir } 1269cdf0e10cSrcweir 1270cdf0e10cSrcweir //-------------------------------------------------------------------------- 1271cdf0e10cSrcweir 1272cdf0e10cSrcweir SalLayout* X11SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel ) 1273cdf0e10cSrcweir { 1274cdf0e10cSrcweir SalLayout* pLayout = NULL; 1275cdf0e10cSrcweir 1276cdf0e10cSrcweir if( mpServerFont[ nFallbackLevel ] 1277cdf0e10cSrcweir && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) ) 1278cdf0e10cSrcweir { 1279cdf0e10cSrcweir #ifdef ENABLE_GRAPHITE 1280cdf0e10cSrcweir // Is this a Graphite font? 1281cdf0e10cSrcweir if (!bDisableGraphite_ && 1282cdf0e10cSrcweir GraphiteFontAdaptor::IsGraphiteEnabledFont(*mpServerFont[nFallbackLevel])) 1283cdf0e10cSrcweir { 1284cdf0e10cSrcweir sal_Int32 xdpi, ydpi; 1285cdf0e10cSrcweir 1286cdf0e10cSrcweir xdpi = GetDisplay()->GetResolution().A(); 1287cdf0e10cSrcweir ydpi = GetDisplay()->GetResolution().B(); 1288cdf0e10cSrcweir 1289cdf0e10cSrcweir GraphiteFontAdaptor * pGrfont = new GraphiteFontAdaptor( *mpServerFont[nFallbackLevel], xdpi, ydpi); 1290cdf0e10cSrcweir if (!pGrfont) return NULL; 1291cdf0e10cSrcweir pLayout = new GraphiteServerFontLayout(pGrfont); 1292cdf0e10cSrcweir } 1293cdf0e10cSrcweir else 1294cdf0e10cSrcweir #endif 1295cdf0e10cSrcweir pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] ); 1296cdf0e10cSrcweir } 1297cdf0e10cSrcweir 1298cdf0e10cSrcweir return pLayout; 1299cdf0e10cSrcweir } 1300cdf0e10cSrcweir 1301cdf0e10cSrcweir //-------------------------------------------------------------------------- 1302cdf0e10cSrcweir 1303cdf0e10cSrcweir SystemFontData X11SalGraphics::GetSysFontData( int nFallbacklevel ) const 1304cdf0e10cSrcweir { 1305cdf0e10cSrcweir SystemFontData aSysFontData; 1306cdf0e10cSrcweir aSysFontData.nSize = sizeof( SystemFontData ); 1307cdf0e10cSrcweir aSysFontData.nFontId = 0; 1308cdf0e10cSrcweir 1309cdf0e10cSrcweir if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1; 1310cdf0e10cSrcweir if (nFallbacklevel < 0 ) nFallbacklevel = 0; 1311cdf0e10cSrcweir 1312cdf0e10cSrcweir if (mpServerFont[nFallbacklevel] != NULL) 1313cdf0e10cSrcweir { 1314cdf0e10cSrcweir ServerFont* rFont = mpServerFont[nFallbacklevel]; 1315cdf0e10cSrcweir aSysFontData.nFontId = rFont->GetFtFace(); 1316cdf0e10cSrcweir aSysFontData.nFontFlags = rFont->GetLoadFlags(); 1317cdf0e10cSrcweir aSysFontData.bFakeBold = rFont->NeedsArtificialBold(); 1318cdf0e10cSrcweir aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic(); 1319cdf0e10cSrcweir aSysFontData.bAntialias = rFont->GetAntialiasAdvice(); 1320cdf0e10cSrcweir aSysFontData.bVerticalCharacterType = rFont->GetFontSelData().mbVertical; 1321cdf0e10cSrcweir } 1322cdf0e10cSrcweir 1323cdf0e10cSrcweir return aSysFontData; 1324cdf0e10cSrcweir } 1325cdf0e10cSrcweir 1326cdf0e10cSrcweir //-------------------------------------------------------------------------- 1327cdf0e10cSrcweir 1328cdf0e10cSrcweir sal_Bool X11SalGraphics::CreateFontSubset( 1329cdf0e10cSrcweir const rtl::OUString& rToFile, 1330cdf0e10cSrcweir const ImplFontData* pFont, 1331cdf0e10cSrcweir sal_Int32* pGlyphIDs, 1332cdf0e10cSrcweir sal_uInt8* pEncoding, 1333cdf0e10cSrcweir sal_Int32* pWidths, 1334cdf0e10cSrcweir int nGlyphCount, 1335cdf0e10cSrcweir FontSubsetInfo& rInfo 1336cdf0e10cSrcweir ) 1337cdf0e10cSrcweir { 1338cdf0e10cSrcweir // in this context the pFont->GetFontId() is a valid PSP 1339cdf0e10cSrcweir // font since they are the only ones left after the PDF 1340cdf0e10cSrcweir // export has filtered its list of subsettable fonts (for 1341cdf0e10cSrcweir // which this method was created). The correct way would 1342cdf0e10cSrcweir // be to have the GlyphCache search for the ImplFontData pFont 1343cdf0e10cSrcweir psp::fontID aFont = pFont->GetFontId(); 1344cdf0e10cSrcweir 1345cdf0e10cSrcweir psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); 1346cdf0e10cSrcweir bool bSuccess = rMgr.createFontSubset( rInfo, 1347cdf0e10cSrcweir aFont, 1348cdf0e10cSrcweir rToFile, 1349cdf0e10cSrcweir pGlyphIDs, 1350cdf0e10cSrcweir pEncoding, 1351cdf0e10cSrcweir pWidths, 1352cdf0e10cSrcweir nGlyphCount ); 1353cdf0e10cSrcweir return bSuccess; 1354cdf0e10cSrcweir } 1355cdf0e10cSrcweir 1356cdf0e10cSrcweir //-------------------------------------------------------------------------- 1357cdf0e10cSrcweir 1358cdf0e10cSrcweir const void* X11SalGraphics::GetEmbedFontData( const ImplFontData* pFont, const sal_Ucs* pUnicodes, sal_Int32* pWidths, FontSubsetInfo& rInfo, long* pDataLen ) 1359cdf0e10cSrcweir { 1360cdf0e10cSrcweir // in this context the pFont->GetFontId() is a valid PSP 1361cdf0e10cSrcweir // font since they are the only ones left after the PDF 1362cdf0e10cSrcweir // export has filtered its list of subsettable fonts (for 1363cdf0e10cSrcweir // which this method was created). The correct way would 1364cdf0e10cSrcweir // be to have the GlyphCache search for the ImplFontData pFont 1365cdf0e10cSrcweir psp::fontID aFont = pFont->GetFontId(); 1366cdf0e10cSrcweir return PspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen ); 1367cdf0e10cSrcweir } 1368cdf0e10cSrcweir 1369cdf0e10cSrcweir //-------------------------------------------------------------------------- 1370cdf0e10cSrcweir 1371cdf0e10cSrcweir void X11SalGraphics::FreeEmbedFontData( const void* pData, long nLen ) 1372cdf0e10cSrcweir { 1373cdf0e10cSrcweir PspGraphics::DoFreeEmbedFontData( pData, nLen ); 1374cdf0e10cSrcweir } 1375cdf0e10cSrcweir 1376cdf0e10cSrcweir //-------------------------------------------------------------------------- 1377cdf0e10cSrcweir 1378cdf0e10cSrcweir const Ucs2SIntMap* X11SalGraphics::GetFontEncodingVector( const ImplFontData* pFont, const Ucs2OStrMap** pNonEncoded ) 1379cdf0e10cSrcweir { 1380cdf0e10cSrcweir // in this context the pFont->GetFontId() is a valid PSP 1381cdf0e10cSrcweir // font since they are the only ones left after the PDF 1382cdf0e10cSrcweir // export has filtered its list of subsettable fonts (for 1383cdf0e10cSrcweir // which this method was created). The correct way would 1384cdf0e10cSrcweir // be to have the GlyphCache search for the ImplFontData pFont 1385cdf0e10cSrcweir psp::fontID aFont = pFont->GetFontId(); 1386cdf0e10cSrcweir return PspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded ); 1387cdf0e10cSrcweir } 1388cdf0e10cSrcweir 1389cdf0e10cSrcweir //-------------------------------------------------------------------------- 1390cdf0e10cSrcweir 1391cdf0e10cSrcweir void X11SalGraphics::GetGlyphWidths( const ImplFontData* pFont, 1392cdf0e10cSrcweir bool bVertical, 1393cdf0e10cSrcweir Int32Vector& rWidths, 1394cdf0e10cSrcweir Ucs2UIntMap& rUnicodeEnc ) 1395cdf0e10cSrcweir { 1396cdf0e10cSrcweir // in this context the pFont->GetFontId() is a valid PSP 1397cdf0e10cSrcweir // font since they are the only ones left after the PDF 1398cdf0e10cSrcweir // export has filtered its list of subsettable fonts (for 1399cdf0e10cSrcweir // which this method was created). The correct way would 1400cdf0e10cSrcweir // be to have the GlyphCache search for the ImplFontData pFont 1401cdf0e10cSrcweir psp::fontID aFont = pFont->GetFontId(); 1402cdf0e10cSrcweir PspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc ); 1403cdf0e10cSrcweir } 1404cdf0e10cSrcweir 1405cdf0e10cSrcweir // =========================================================================== 1406cdf0e10cSrcweir // platform specific font substitution hooks 1407cdf0e10cSrcweir 1408cdf0e10cSrcweir class FcPreMatchSubstititution 1409cdf0e10cSrcweir : public ImplPreMatchFontSubstitution 1410cdf0e10cSrcweir { 1411cdf0e10cSrcweir public: 1412cdf0e10cSrcweir bool FindFontSubstitute( ImplFontSelectData& ) const; 1413cdf0e10cSrcweir }; 1414cdf0e10cSrcweir 1415cdf0e10cSrcweir class FcGlyphFallbackSubstititution 1416cdf0e10cSrcweir : public ImplGlyphFallbackFontSubstitution 1417cdf0e10cSrcweir { 1418cdf0e10cSrcweir // TODO: add a cache 1419cdf0e10cSrcweir public: 1420cdf0e10cSrcweir bool FindFontSubstitute( ImplFontSelectData&, OUString& rMissingCodes ) const; 1421cdf0e10cSrcweir }; 1422cdf0e10cSrcweir 1423cdf0e10cSrcweir void RegisterFontSubstitutors( ImplDevFontList* pList ) 1424cdf0e10cSrcweir { 1425cdf0e10cSrcweir // init font substitution defaults 1426cdf0e10cSrcweir int nDisableBits = 0; 1427cdf0e10cSrcweir #ifdef SOLARIS 1428cdf0e10cSrcweir nDisableBits = 1; // disable "font fallback" here on default 1429cdf0e10cSrcweir #endif 1430cdf0e10cSrcweir // apply the environment variable if any 1431cdf0e10cSrcweir const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" ); 1432cdf0e10cSrcweir if( pEnvStr ) 1433cdf0e10cSrcweir { 1434cdf0e10cSrcweir if( (*pEnvStr >= '0') && (*pEnvStr <= '9') ) 1435cdf0e10cSrcweir nDisableBits = (*pEnvStr - '0'); 1436cdf0e10cSrcweir else 1437cdf0e10cSrcweir nDisableBits = ~0U; // no specific bits set: disable all 1438cdf0e10cSrcweir } 1439cdf0e10cSrcweir 1440cdf0e10cSrcweir // register font fallback substitutions (unless disabled by bit0) 1441cdf0e10cSrcweir if( (nDisableBits & 1) == 0 ) 1442cdf0e10cSrcweir { 1443cdf0e10cSrcweir static FcPreMatchSubstititution aSubstPreMatch; 1444cdf0e10cSrcweir pList->SetPreMatchHook( &aSubstPreMatch ); 1445cdf0e10cSrcweir } 1446cdf0e10cSrcweir 1447cdf0e10cSrcweir // register glyph fallback substitutions (unless disabled by bit1) 1448cdf0e10cSrcweir if( (nDisableBits & 2) == 0 ) 1449cdf0e10cSrcweir { 1450cdf0e10cSrcweir static FcGlyphFallbackSubstititution aSubstFallback; 1451cdf0e10cSrcweir pList->SetFallbackHook( &aSubstFallback ); 1452cdf0e10cSrcweir } 1453cdf0e10cSrcweir } 1454cdf0e10cSrcweir 1455cdf0e10cSrcweir // ----------------------------------------------------------------------- 1456cdf0e10cSrcweir 1457cdf0e10cSrcweir static ImplFontSelectData GetFcSubstitute(const ImplFontSelectData &rFontSelData, OUString& rMissingCodes ) 1458cdf0e10cSrcweir { 1459cdf0e10cSrcweir ImplFontSelectData aRet(rFontSelData); 1460cdf0e10cSrcweir 1461cdf0e10cSrcweir const rtl::OString aLangAttrib = MsLangId::convertLanguageToIsoByteString( rFontSelData.meLanguage ); 1462cdf0e10cSrcweir 1463cdf0e10cSrcweir psp::italic::type eItalic = psp::italic::Unknown; 1464cdf0e10cSrcweir if( rFontSelData.GetSlant() != ITALIC_DONTKNOW ) 1465cdf0e10cSrcweir { 1466cdf0e10cSrcweir switch( rFontSelData.GetSlant() ) 1467cdf0e10cSrcweir { 1468cdf0e10cSrcweir case ITALIC_NONE: eItalic = psp::italic::Upright; break; 1469cdf0e10cSrcweir case ITALIC_NORMAL: eItalic = psp::italic::Italic; break; 1470cdf0e10cSrcweir case ITALIC_OBLIQUE: eItalic = psp::italic::Oblique; break; 1471cdf0e10cSrcweir default: 1472cdf0e10cSrcweir break; 1473cdf0e10cSrcweir } 1474cdf0e10cSrcweir } 1475cdf0e10cSrcweir 1476cdf0e10cSrcweir psp::weight::type eWeight = psp::weight::Unknown; 1477cdf0e10cSrcweir if( rFontSelData.GetWeight() != WEIGHT_DONTKNOW ) 1478cdf0e10cSrcweir { 1479cdf0e10cSrcweir switch( rFontSelData.GetWeight() ) 1480cdf0e10cSrcweir { 1481cdf0e10cSrcweir case WEIGHT_THIN: eWeight = psp::weight::Thin; break; 1482cdf0e10cSrcweir case WEIGHT_ULTRALIGHT: eWeight = psp::weight::UltraLight; break; 1483cdf0e10cSrcweir case WEIGHT_LIGHT: eWeight = psp::weight::Light; break; 1484cdf0e10cSrcweir case WEIGHT_SEMILIGHT: eWeight = psp::weight::SemiLight; break; 1485cdf0e10cSrcweir case WEIGHT_NORMAL: eWeight = psp::weight::Normal; break; 1486cdf0e10cSrcweir case WEIGHT_MEDIUM: eWeight = psp::weight::Medium; break; 1487cdf0e10cSrcweir case WEIGHT_SEMIBOLD: eWeight = psp::weight::SemiBold; break; 1488cdf0e10cSrcweir case WEIGHT_BOLD: eWeight = psp::weight::Bold; break; 1489cdf0e10cSrcweir case WEIGHT_ULTRABOLD: eWeight = psp::weight::UltraBold; break; 1490cdf0e10cSrcweir case WEIGHT_BLACK: eWeight = psp::weight::Black; break; 1491cdf0e10cSrcweir default: 1492cdf0e10cSrcweir break; 1493cdf0e10cSrcweir } 1494cdf0e10cSrcweir } 1495cdf0e10cSrcweir 1496cdf0e10cSrcweir psp::width::type eWidth = psp::width::Unknown; 1497cdf0e10cSrcweir if( rFontSelData.GetWidthType() != WIDTH_DONTKNOW ) 1498cdf0e10cSrcweir { 1499cdf0e10cSrcweir switch( rFontSelData.GetWidthType() ) 1500cdf0e10cSrcweir { 1501cdf0e10cSrcweir case WIDTH_ULTRA_CONDENSED: eWidth = psp::width::UltraCondensed; break; 1502cdf0e10cSrcweir case WIDTH_EXTRA_CONDENSED: eWidth = psp::width::ExtraCondensed; break; 1503cdf0e10cSrcweir case WIDTH_CONDENSED: eWidth = psp::width::Condensed; break; 1504cdf0e10cSrcweir case WIDTH_SEMI_CONDENSED: eWidth = psp::width::SemiCondensed; break; 1505cdf0e10cSrcweir case WIDTH_NORMAL: eWidth = psp::width::Normal; break; 1506cdf0e10cSrcweir case WIDTH_SEMI_EXPANDED: eWidth = psp::width::SemiExpanded; break; 1507cdf0e10cSrcweir case WIDTH_EXPANDED: eWidth = psp::width::Expanded; break; 1508cdf0e10cSrcweir case WIDTH_EXTRA_EXPANDED: eWidth = psp::width::ExtraExpanded; break; 1509cdf0e10cSrcweir case WIDTH_ULTRA_EXPANDED: eWidth = psp::width::UltraExpanded; break; 1510cdf0e10cSrcweir default: 1511cdf0e10cSrcweir break; 1512cdf0e10cSrcweir } 1513cdf0e10cSrcweir } 1514cdf0e10cSrcweir 1515cdf0e10cSrcweir psp::pitch::type ePitch = psp::pitch::Unknown; 1516cdf0e10cSrcweir if( rFontSelData.GetPitch() != PITCH_DONTKNOW ) 1517cdf0e10cSrcweir { 1518cdf0e10cSrcweir switch( rFontSelData.GetPitch() ) 1519cdf0e10cSrcweir { 1520cdf0e10cSrcweir case PITCH_FIXED: ePitch=psp::pitch::Fixed; break; 1521cdf0e10cSrcweir case PITCH_VARIABLE: ePitch=psp::pitch::Variable; break; 1522cdf0e10cSrcweir default: 1523cdf0e10cSrcweir break; 1524cdf0e10cSrcweir } 1525cdf0e10cSrcweir } 1526cdf0e10cSrcweir 1527cdf0e10cSrcweir const psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); 1528cdf0e10cSrcweir aRet.maSearchName = rMgr.Substitute( rFontSelData.maTargetName, rMissingCodes, aLangAttrib, eItalic, eWeight, eWidth, ePitch); 1529cdf0e10cSrcweir 1530cdf0e10cSrcweir switch (eItalic) 1531cdf0e10cSrcweir { 1532cdf0e10cSrcweir case psp::italic::Upright: aRet.meItalic = ITALIC_NONE; break; 1533cdf0e10cSrcweir case psp::italic::Italic: aRet.meItalic = ITALIC_NORMAL; break; 1534cdf0e10cSrcweir case psp::italic::Oblique: aRet.meItalic = ITALIC_OBLIQUE; break; 1535cdf0e10cSrcweir default: 1536cdf0e10cSrcweir break; 1537cdf0e10cSrcweir } 1538cdf0e10cSrcweir 1539cdf0e10cSrcweir switch (eWeight) 1540cdf0e10cSrcweir { 1541cdf0e10cSrcweir case psp::weight::Thin: aRet.meWeight = WEIGHT_THIN; break; 1542cdf0e10cSrcweir case psp::weight::UltraLight: aRet.meWeight = WEIGHT_ULTRALIGHT; break; 1543cdf0e10cSrcweir case psp::weight::Light: aRet.meWeight = WEIGHT_LIGHT; break; 1544cdf0e10cSrcweir case psp::weight::SemiLight: aRet.meWeight = WEIGHT_SEMILIGHT; break; 1545cdf0e10cSrcweir case psp::weight::Normal: aRet.meWeight = WEIGHT_NORMAL; break; 1546cdf0e10cSrcweir case psp::weight::Medium: aRet.meWeight = WEIGHT_MEDIUM; break; 1547cdf0e10cSrcweir case psp::weight::SemiBold: aRet.meWeight = WEIGHT_SEMIBOLD; break; 1548cdf0e10cSrcweir case psp::weight::Bold: aRet.meWeight = WEIGHT_BOLD; break; 1549cdf0e10cSrcweir case psp::weight::UltraBold: aRet.meWeight = WEIGHT_ULTRABOLD; break; 1550cdf0e10cSrcweir case psp::weight::Black: aRet.meWeight = WEIGHT_BLACK; break; 1551cdf0e10cSrcweir default: 1552cdf0e10cSrcweir break; 1553cdf0e10cSrcweir } 1554cdf0e10cSrcweir 1555cdf0e10cSrcweir switch (eWidth) 1556cdf0e10cSrcweir { 1557cdf0e10cSrcweir case psp::width::UltraCondensed: aRet.meWidthType = WIDTH_ULTRA_CONDENSED; break; 1558cdf0e10cSrcweir case psp::width::ExtraCondensed: aRet.meWidthType = WIDTH_EXTRA_CONDENSED; break; 1559cdf0e10cSrcweir case psp::width::Condensed: aRet.meWidthType = WIDTH_CONDENSED; break; 1560cdf0e10cSrcweir case psp::width::SemiCondensed: aRet.meWidthType = WIDTH_SEMI_CONDENSED; break; 1561cdf0e10cSrcweir case psp::width::Normal: aRet.meWidthType = WIDTH_NORMAL; break; 1562cdf0e10cSrcweir case psp::width::SemiExpanded: aRet.meWidthType = WIDTH_SEMI_EXPANDED; break; 1563cdf0e10cSrcweir case psp::width::Expanded: aRet.meWidthType = WIDTH_EXPANDED; break; 1564cdf0e10cSrcweir case psp::width::ExtraExpanded: aRet.meWidthType = WIDTH_EXTRA_EXPANDED; break; 1565cdf0e10cSrcweir case psp::width::UltraExpanded: aRet.meWidthType = WIDTH_ULTRA_EXPANDED; break; 1566cdf0e10cSrcweir default: 1567cdf0e10cSrcweir break; 1568cdf0e10cSrcweir } 1569cdf0e10cSrcweir 1570cdf0e10cSrcweir switch (ePitch) 1571cdf0e10cSrcweir { 1572cdf0e10cSrcweir case psp::pitch::Fixed: aRet.mePitch = PITCH_FIXED; break; 1573cdf0e10cSrcweir case psp::pitch::Variable: aRet.mePitch = PITCH_VARIABLE; break; 1574cdf0e10cSrcweir default: 1575cdf0e10cSrcweir break; 1576cdf0e10cSrcweir } 1577cdf0e10cSrcweir 1578cdf0e10cSrcweir return aRet; 1579cdf0e10cSrcweir } 1580cdf0e10cSrcweir 1581cdf0e10cSrcweir namespace 1582cdf0e10cSrcweir { 1583cdf0e10cSrcweir bool uselessmatch(const ImplFontSelectData &rOrig, const ImplFontSelectData &rNew) 1584cdf0e10cSrcweir { 1585cdf0e10cSrcweir return 1586cdf0e10cSrcweir ( 1587cdf0e10cSrcweir rOrig.maTargetName == rNew.maSearchName && 1588cdf0e10cSrcweir rOrig.meWeight == rNew.meWeight && 1589cdf0e10cSrcweir rOrig.meItalic == rNew.meItalic && 1590cdf0e10cSrcweir rOrig.mePitch == rNew.mePitch && 1591cdf0e10cSrcweir rOrig.meWidthType == rNew.meWidthType 1592cdf0e10cSrcweir ); 1593cdf0e10cSrcweir } 1594cdf0e10cSrcweir } 1595cdf0e10cSrcweir 1596cdf0e10cSrcweir //-------------------------------------------------------------------------- 1597cdf0e10cSrcweir 1598cdf0e10cSrcweir bool FcPreMatchSubstititution::FindFontSubstitute( ImplFontSelectData &rFontSelData ) const 1599cdf0e10cSrcweir { 1600cdf0e10cSrcweir // We dont' actually want to talk to Fontconfig at all for symbol fonts 1601cdf0e10cSrcweir if( rFontSelData.IsSymbolFont() ) 1602cdf0e10cSrcweir return false; 1603cdf0e10cSrcweir // StarSymbol is a unicode font, but it still deserves the symbol flag 1604cdf0e10cSrcweir if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10) 1605cdf0e10cSrcweir || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) ) 1606cdf0e10cSrcweir return false; 1607cdf0e10cSrcweir 1608cdf0e10cSrcweir rtl::OUString aDummy; 1609cdf0e10cSrcweir const ImplFontSelectData aOut = GetFcSubstitute( rFontSelData, aDummy ); 1610cdf0e10cSrcweir // TODO: cache the font substitution suggestion 1611cdf0e10cSrcweir // FC doing it would be preferable because it knows the invariables 1612cdf0e10cSrcweir // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans 1613cdf0e10cSrcweir // whereas we would have to check for every size or attribute 1614cdf0e10cSrcweir if( !aOut.maSearchName.Len() ) 1615cdf0e10cSrcweir return false; 1616cdf0e10cSrcweir 1617cdf0e10cSrcweir const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut ); 1618cdf0e10cSrcweir 1619cdf0e10cSrcweir #ifdef DEBUG 1620cdf0e10cSrcweir const ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 ); 1621cdf0e10cSrcweir const ByteString aSubstName( aOut.maSearchName, RTL_TEXTENCODING_UTF8 ); 1622cdf0e10cSrcweir printf( "FcPreMatchSubstititution \"%s\" bipw=%d%d%d%d -> ", 1623cdf0e10cSrcweir aOrigName.GetBuffer(), rFontSelData.meWeight, rFontSelData.meItalic, 1624cdf0e10cSrcweir rFontSelData.mePitch, rFontSelData.meWidthType ); 1625cdf0e10cSrcweir if( !bHaveSubstitute ) 1626cdf0e10cSrcweir printf( "no substitute available\n" ); 1627cdf0e10cSrcweir else 1628cdf0e10cSrcweir printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.GetBuffer(), 1629cdf0e10cSrcweir aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType ); 1630cdf0e10cSrcweir #endif 1631cdf0e10cSrcweir 1632cdf0e10cSrcweir if( bHaveSubstitute ) 1633cdf0e10cSrcweir rFontSelData = aOut; 1634cdf0e10cSrcweir 1635cdf0e10cSrcweir return bHaveSubstitute; 1636cdf0e10cSrcweir } 1637cdf0e10cSrcweir 1638cdf0e10cSrcweir // ----------------------------------------------------------------------- 1639cdf0e10cSrcweir 1640cdf0e10cSrcweir bool FcGlyphFallbackSubstititution::FindFontSubstitute( ImplFontSelectData& rFontSelData, 1641cdf0e10cSrcweir rtl::OUString& rMissingCodes ) const 1642cdf0e10cSrcweir { 1643cdf0e10cSrcweir // We dont' actually want to talk to Fontconfig at all for symbol fonts 1644cdf0e10cSrcweir if( rFontSelData.IsSymbolFont() ) 1645cdf0e10cSrcweir return false; 1646cdf0e10cSrcweir // StarSymbol is a unicode font, but it still deserves the symbol flag 1647cdf0e10cSrcweir if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10) 1648cdf0e10cSrcweir || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) ) 1649cdf0e10cSrcweir return false; 1650cdf0e10cSrcweir 1651cdf0e10cSrcweir const ImplFontSelectData aOut = GetFcSubstitute( rFontSelData, rMissingCodes ); 1652cdf0e10cSrcweir // TODO: cache the unicode + srcfont specific result 1653cdf0e10cSrcweir // FC doing it would be preferable because it knows the invariables 1654cdf0e10cSrcweir // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans 1655cdf0e10cSrcweir // whereas we would have to check for every size or attribute 1656cdf0e10cSrcweir if( !aOut.maSearchName.Len() ) 1657cdf0e10cSrcweir return false; 1658cdf0e10cSrcweir 1659cdf0e10cSrcweir const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut ); 1660cdf0e10cSrcweir 1661cdf0e10cSrcweir #ifdef DEBUG 1662cdf0e10cSrcweir const ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 ); 1663cdf0e10cSrcweir const ByteString aSubstName( aOut.maSearchName, RTL_TEXTENCODING_UTF8 ); 1664cdf0e10cSrcweir printf( "FcGFSubstititution \"%s\" bipw=%d%d%d%d ->", 1665cdf0e10cSrcweir aOrigName.GetBuffer(), rFontSelData.meWeight, rFontSelData.meItalic, 1666cdf0e10cSrcweir rFontSelData.mePitch, rFontSelData.meWidthType ); 1667cdf0e10cSrcweir if( !bHaveSubstitute ) 1668cdf0e10cSrcweir printf( "no substitute available\n" ); 1669cdf0e10cSrcweir else 1670cdf0e10cSrcweir printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.GetBuffer(), 1671cdf0e10cSrcweir aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType ); 1672cdf0e10cSrcweir #endif 1673cdf0e10cSrcweir 1674cdf0e10cSrcweir if( bHaveSubstitute ) 1675cdf0e10cSrcweir rFontSelData = aOut; 1676cdf0e10cSrcweir 1677cdf0e10cSrcweir return bHaveSubstitute; 1678cdf0e10cSrcweir } 1679cdf0e10cSrcweir 1680cdf0e10cSrcweir // =========================================================================== 1681cdf0e10cSrcweir 1682