Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <string.h>
31 : : #include <stdio.h>
32 : : #include <stdlib.h>
33 : : #include <math.h>
34 : : #include <unistd.h>
35 : : #include <fcntl.h>
36 : : #include <fontconfig/fontconfig.h>
37 : : #include <sys/mman.h>
38 : : #include <sys/stat.h>
39 : : #include <sys/types.h>
40 : :
41 : : #include "sal/alloca.h"
42 : : #include "sal/types.h"
43 : :
44 : : #include "rtl/tencinfo.h"
45 : :
46 : : #include "osl/file.hxx"
47 : : #include "osl/module.hxx"
48 : :
49 : : #include "tools/debug.hxx"
50 : : #include "tools/stream.hxx"
51 : :
52 : : #include "basegfx/polygon/b2dpolypolygon.hxx"
53 : :
54 : : #include "i18npool/mslangid.hxx"
55 : :
56 : : #include <boost/unordered_set.hpp>
57 : :
58 : : #include <vcl/sysdata.hxx>
59 : : #include "generic/printergfx.hxx"
60 : : #include "vcl/fontmanager.hxx"
61 : : #include "vcl/jobdata.hxx"
62 : : #include "vcl/printerinfomanager.hxx"
63 : : #include "vcl/svapp.hxx"
64 : :
65 : : #include "unx/salunx.h"
66 : : #include "unx/saldata.hxx"
67 : : #include "unx/saldisp.hxx"
68 : : #include "unx/salgdi.h"
69 : : #include "generic/genpspgraphics.h"
70 : : #include "unx/salvd.h"
71 : :
72 : : #include "gcach_xpeer.hxx"
73 : : #include "xrender_peer.hxx"
74 : : #include "impfont.hxx"
75 : : #include "salframe.hxx"
76 : : #include "outdev.h"
77 : :
78 : : #ifdef ENABLE_GRAPHITE
79 : : #include <graphite_layout.hxx>
80 : : #include <graphite_serverfont.hxx>
81 : : #endif
82 : :
83 : : #include <cairo.h>
84 : : #include <cairo-ft.h>
85 : : #include <cairo-xlib.h>
86 : : #include <cairo-xlib-xrender.h>
87 : :
88 : : struct BOX
89 : : {
90 : : short x1, x2, y1, y2;
91 : : };
92 : : struct _XRegion
93 : : {
94 : : long size;
95 : : long numRects;
96 : : BOX *rects;
97 : : BOX extents;
98 : : };
99 : : using ::rtl::OUString;
100 : : // ===========================================================================
101 : :
102 : : // PspKernInfo allows on-demand-querying of psprint provided kerning info (#i29881#)
103 : 0 : class PspKernInfo : public ExtraKernInfo
104 : : {
105 : : public:
106 : 0 : PspKernInfo( int nFontId ) : ExtraKernInfo(nFontId) {}
107 : : protected:
108 : : virtual void Initialize() const;
109 : : };
110 : :
111 : : //--------------------------------------------------------------------------
112 : :
113 : 0 : void PspKernInfo::Initialize() const
114 : : {
115 : 0 : mbInitialized = true;
116 : :
117 : : // get the kerning pairs from psprint
118 : 0 : const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
119 : : typedef std::list< psp::KernPair > PspKernPairs;
120 : 0 : const PspKernPairs& rKernPairs = rMgr.getKernPairs( mnFontId );
121 : 0 : if( rKernPairs.empty() )
122 : 0 : return;
123 : :
124 : 0 : PspKernPairs::const_iterator it = rKernPairs.begin();
125 : 0 : for(; it != rKernPairs.end(); ++it )
126 : : {
127 : 0 : ImplKernPairData aKernPair = { it->first, it->second, it->kern_x };
128 : 0 : maUnicodeKernPairs.insert( aKernPair );
129 : : }
130 : : }
131 : :
132 : : // ----------------------------------------------------------------------------
133 : : //
134 : : // X11SalGraphics
135 : : //
136 : : // ----------------------------------------------------------------------------
137 : :
138 : : GC
139 : 0 : X11SalGraphics::GetFontGC()
140 : : {
141 : 0 : Display *pDisplay = GetXDisplay();
142 : :
143 : 0 : if( !pFontGC_ )
144 : : {
145 : : XGCValues values;
146 : 0 : values.subwindow_mode = ClipByChildren;
147 : 0 : values.fill_rule = EvenOddRule; // Pict import/ Gradient
148 : 0 : values.graphics_exposures = False;
149 : 0 : values.foreground = nTextPixel_;
150 : : pFontGC_ = XCreateGC( pDisplay, hDrawable_,
151 : : GCSubwindowMode | GCFillRule
152 : : | GCGraphicsExposures | GCForeground,
153 : 0 : &values );
154 : : }
155 : 0 : if( !bFontGC_ )
156 : : {
157 : 0 : XSetForeground( pDisplay, pFontGC_, nTextPixel_ );
158 : 0 : SetClipRegion( pFontGC_ );
159 : 0 : bFontGC_ = sal_True;
160 : : }
161 : :
162 : 0 : return pFontGC_;
163 : : }
164 : :
165 : : //--------------------------------------------------------------------------
166 : :
167 : 0 : bool X11SalGraphics::setFont( const FontSelectPattern *pEntry, int nFallbackLevel )
168 : : {
169 : : // release all no longer needed font resources
170 : 0 : for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
171 : : {
172 : 0 : if( mpServerFont[i] != NULL )
173 : : {
174 : : // old server side font is no longer referenced
175 : 0 : GlyphCache::GetInstance().UncacheFont( *mpServerFont[i] );
176 : 0 : mpServerFont[i] = NULL;
177 : : }
178 : : }
179 : :
180 : : // return early if there is no new font
181 : 0 : if( !pEntry )
182 : 0 : return false;
183 : :
184 : 0 : bFontVertical_ = pEntry->mbVertical;
185 : :
186 : : // return early if this is not a valid font for this graphics
187 : 0 : if( !pEntry->mpFontData )
188 : 0 : return false;
189 : :
190 : : // handle the request for a non-native X11-font => use the GlyphCache
191 : 0 : ServerFont* pServerFont = GlyphCache::GetInstance().CacheFont( *pEntry );
192 : 0 : if( pServerFont != NULL )
193 : : {
194 : : // ignore fonts with e.g. corrupted font files
195 : 0 : if( !pServerFont->TestFont() )
196 : : {
197 : 0 : GlyphCache::GetInstance().UncacheFont( *pServerFont );
198 : 0 : return false;
199 : : }
200 : :
201 : : // register to use the font
202 : 0 : mpServerFont[ nFallbackLevel ] = pServerFont;
203 : :
204 : : // apply font specific-hint settings if needed
205 : : // TODO: also disable it for reference devices
206 : 0 : if( !bPrinter_ )
207 : : {
208 : 0 : ImplServerFontEntry* pSFE = static_cast<ImplServerFontEntry*>( pEntry->mpFontEntry );
209 : 0 : pSFE->HandleFontOptions();
210 : : }
211 : :
212 : 0 : return true;
213 : : }
214 : :
215 : 0 : return false;
216 : : }
217 : :
218 : : ImplFontOptions* GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize);
219 : :
220 : 0 : void ImplServerFontEntry::HandleFontOptions( void )
221 : : {
222 : 0 : if( !mpServerFont )
223 : 0 : return;
224 : 0 : if( !mbGotFontOptions )
225 : : {
226 : : // get and cache the font options
227 : 0 : mbGotFontOptions = true;
228 : : mpFontOptions.reset(GetFCFontOptions( *maFontSelData.mpFontData,
229 : 0 : maFontSelData.mnHeight ));
230 : : }
231 : : // apply the font options
232 : 0 : mpServerFont->SetFontOptions( mpFontOptions );
233 : : }
234 : :
235 : : //--------------------------------------------------------------------------
236 : :
237 : 0 : CairoFontsCache::LRUFonts CairoFontsCache::maLRUFonts;
238 : : int CairoFontsCache::mnRefCount = 0;
239 : :
240 : 0 : CairoFontsCache::CairoFontsCache()
241 : : {
242 : 0 : ++mnRefCount;
243 : 0 : }
244 : :
245 : 0 : CairoFontsCache::~CairoFontsCache()
246 : : {
247 : 0 : --mnRefCount;
248 : 0 : if (!mnRefCount && !maLRUFonts.empty())
249 : : {
250 : 0 : LRUFonts::iterator aEnd = maLRUFonts.end();
251 : 0 : for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
252 : 0 : cairo_font_face_destroy((cairo_font_face_t*)aI->first);
253 : : }
254 : 0 : }
255 : :
256 : 0 : void CairoFontsCache::CacheFont(void *pFont, const CairoFontsCache::CacheId &rId)
257 : : {
258 : 0 : maLRUFonts.push_front( std::pair<void*, CairoFontsCache::CacheId>(pFont, rId) );
259 : 0 : if (maLRUFonts.size() > 8)
260 : : {
261 : 0 : cairo_font_face_destroy((cairo_font_face_t*)maLRUFonts.back().first);
262 : 0 : maLRUFonts.pop_back();
263 : : }
264 : 0 : }
265 : :
266 : 0 : void* CairoFontsCache::FindCachedFont(const CairoFontsCache::CacheId &rId)
267 : : {
268 : 0 : LRUFonts::iterator aEnd = maLRUFonts.end();
269 : 0 : for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
270 : 0 : if (aI->second == rId)
271 : 0 : return aI->first;
272 : 0 : return NULL;
273 : : }
274 : :
275 : : namespace
276 : : {
277 : 0 : bool hasRotation(int nRotation)
278 : : {
279 : 0 : return nRotation != 0;
280 : : }
281 : :
282 : 0 : double toRadian(int nDegree10th)
283 : : {
284 : 0 : return (3600 - (nDegree10th)) * M_PI / 1800.0;
285 : : }
286 : : }
287 : :
288 : 0 : void X11SalGraphics::DrawServerFontLayout( const ServerFontLayout& rLayout )
289 : : {
290 : 0 : std::vector<cairo_glyph_t> cairo_glyphs;
291 : 0 : std::vector<int> glyph_extrarotation;
292 : 0 : cairo_glyphs.reserve( 256 );
293 : :
294 : 0 : Point aPos;
295 : : sal_GlyphId aGlyphId;
296 : 0 : for( int nStart = 0; rLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart ); )
297 : : {
298 : : cairo_glyph_t aGlyph;
299 : 0 : aGlyph.index = aGlyphId & GF_IDXMASK;
300 : 0 : aGlyph.x = aPos.X();
301 : 0 : aGlyph.y = aPos.Y();
302 : 0 : cairo_glyphs.push_back(aGlyph);
303 : :
304 : 0 : switch (aGlyphId & GF_ROTMASK)
305 : : {
306 : : case GF_ROTL: // left
307 : 0 : glyph_extrarotation.push_back(1);
308 : 0 : break;
309 : : case GF_ROTR: // right
310 : 0 : glyph_extrarotation.push_back(-1);
311 : 0 : break;
312 : : default:
313 : 0 : glyph_extrarotation.push_back(0);
314 : 0 : break;
315 : : }
316 : : }
317 : :
318 : 0 : if (cairo_glyphs.empty())
319 : : return;
320 : :
321 : : // find a XRenderPictFormat compatible with the Drawable
322 : 0 : XRenderPictFormat* pVisualFormat = GetXRenderFormat();
323 : :
324 : 0 : Display* pDisplay = GetXDisplay();
325 : :
326 : : cairo_surface_t *surface;
327 : :
328 : 0 : if (pVisualFormat)
329 : : {
330 : : surface = cairo_xlib_surface_create_with_xrender_format (
331 : : pDisplay, hDrawable_,
332 : 0 : ScreenOfDisplay(pDisplay, m_nXScreen.getXScreen()),
333 : 0 : pVisualFormat, SAL_MAX_INT16, SAL_MAX_INT16);
334 : : }
335 : : else
336 : : {
337 : : surface = cairo_xlib_surface_create(pDisplay, hDrawable_,
338 : 0 : GetVisual().visual, SAL_MAX_INT16, SAL_MAX_INT16);
339 : : }
340 : :
341 : : DBG_ASSERT( surface!=NULL, "no cairo surface for text" );
342 : 0 : if( !surface )
343 : : return;
344 : :
345 : : /*
346 : : * It might be ideal to cache surface and cairo context between calls and
347 : : * only destroy it when the drawable changes, but to do that we need to at
348 : : * least change the SalFrame etc impls to dtor the SalGraphics *before* the
349 : : * destruction of the windows they reference
350 : : */
351 : 0 : cairo_t *cr = cairo_create(surface);
352 : 0 : cairo_surface_destroy(surface);
353 : :
354 : 0 : if (const void *pOptions = Application::GetSettings().GetStyleSettings().GetCairoFontOptions())
355 : 0 : cairo_set_font_options(cr, static_cast<const cairo_font_options_t*>(pOptions));
356 : :
357 : 0 : if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
358 : : {
359 : 0 : for (long i = 0; i < mpClipRegion->numRects; ++i)
360 : : {
361 : : cairo_rectangle(cr,
362 : 0 : mpClipRegion->rects[i].x1,
363 : 0 : mpClipRegion->rects[i].y1,
364 : 0 : mpClipRegion->rects[i].x2 - mpClipRegion->rects[i].x1,
365 : 0 : mpClipRegion->rects[i].y2 - mpClipRegion->rects[i].y1);
366 : : }
367 : 0 : cairo_clip(cr);
368 : : }
369 : :
370 : : cairo_set_source_rgb(cr,
371 : : SALCOLOR_RED(nTextColor_)/255.0,
372 : : SALCOLOR_GREEN(nTextColor_)/255.0,
373 : 0 : SALCOLOR_BLUE(nTextColor_)/255.0);
374 : :
375 : 0 : ServerFont& rFont = rLayout.GetServerFont();
376 : :
377 : 0 : FT_Face aFace = rFont.GetFtFace();
378 : : CairoFontsCache::CacheId aId;
379 : 0 : aId.maFace = aFace;
380 : 0 : aId.mpOptions = rFont.GetFontOptions().get();
381 : 0 : aId.mbEmbolden = rFont.NeedsArtificialBold();
382 : :
383 : : cairo_matrix_t m;
384 : 0 : const FontSelectPattern& rFSD = rFont.GetFontSelData();
385 : 0 : int nHeight = rFSD.mnHeight;
386 : 0 : int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight;
387 : :
388 : 0 : std::vector<int>::const_iterator aEnd = glyph_extrarotation.end();
389 : 0 : std::vector<int>::const_iterator aStart = glyph_extrarotation.begin();
390 : 0 : std::vector<int>::const_iterator aI = aStart;
391 : 0 : while (aI != aEnd)
392 : : {
393 : 0 : int nGlyphRotation = *aI;
394 : :
395 : 0 : std::vector<int>::const_iterator aNext = std::find_if(aI+1, aEnd, hasRotation);
396 : :
397 : 0 : size_t nStartIndex = std::distance(aStart, aI);
398 : 0 : size_t nLen = std::distance(aI, aNext);
399 : :
400 : 0 : aId.mbVerticalMetrics = nGlyphRotation != 0.0;
401 : 0 : cairo_font_face_t* font_face = (cairo_font_face_t*)m_aCairoFontsCache.FindCachedFont(aId);
402 : 0 : if (!font_face)
403 : : {
404 : 0 : const ImplFontOptions *pOptions = rFont.GetFontOptions().get();
405 : 0 : void *pPattern = pOptions ? pOptions->GetPattern(aFace, aId.mbEmbolden, aId.mbVerticalMetrics) : NULL;
406 : 0 : if (pPattern)
407 : 0 : font_face = cairo_ft_font_face_create_for_pattern(reinterpret_cast<FcPattern*>(pPattern));
408 : 0 : if (!font_face)
409 : 0 : font_face = cairo_ft_font_face_create_for_ft_face(reinterpret_cast<FT_Face>(aFace), rFont.GetLoadFlags());
410 : 0 : m_aCairoFontsCache.CacheFont(font_face, aId);
411 : : }
412 : 0 : cairo_set_font_face(cr, font_face);
413 : :
414 : 0 : cairo_set_font_size(cr, nHeight);
415 : :
416 : 0 : cairo_matrix_init_identity(&m);
417 : :
418 : 0 : if (rLayout.GetOrientation())
419 : 0 : cairo_matrix_rotate(&m, toRadian(rLayout.GetOrientation()));
420 : :
421 : 0 : cairo_matrix_scale(&m, nWidth, nHeight);
422 : :
423 : 0 : if (nGlyphRotation)
424 : : {
425 : 0 : cairo_matrix_rotate(&m, toRadian(nGlyphRotation*900));
426 : :
427 : : cairo_matrix_t em_square;
428 : 0 : cairo_matrix_init_identity(&em_square);
429 : 0 : cairo_get_matrix(cr, &em_square);
430 : :
431 : : cairo_matrix_scale(&em_square, aFace->units_per_EM,
432 : 0 : aFace->units_per_EM);
433 : 0 : cairo_set_matrix(cr, &em_square);
434 : :
435 : : cairo_font_extents_t font_extents;
436 : 0 : cairo_font_extents(cr, &font_extents);
437 : :
438 : 0 : cairo_matrix_init_identity(&em_square);
439 : 0 : cairo_set_matrix(cr, &em_square);
440 : :
441 : : //gives the same positions as pre-cairo conversion, but I don't
442 : : //like them
443 : 0 : double xdiff = 0.0;
444 : 0 : double ydiff = 0.0;
445 : 0 : if (nGlyphRotation == 1)
446 : : {
447 : 0 : ydiff = font_extents.ascent/nHeight;
448 : 0 : xdiff = -font_extents.descent/nHeight;
449 : : }
450 : 0 : else if (nGlyphRotation == -1)
451 : : {
452 : : cairo_text_extents_t text_extents;
453 : 0 : cairo_glyph_extents(cr, &cairo_glyphs[nStartIndex], nLen,
454 : 0 : &text_extents);
455 : :
456 : 0 : xdiff = -text_extents.x_advance/nHeight;
457 : : //to restore an apparent bug in the original X11 impl, replace
458 : : //nHeight with nWidth below
459 : 0 : xdiff += font_extents.descent/nHeight;
460 : : }
461 : 0 : cairo_matrix_translate(&m, xdiff, ydiff);
462 : : }
463 : :
464 : 0 : if (rFont.NeedsArtificialItalic())
465 : : {
466 : : cairo_matrix_t shear;
467 : 0 : cairo_matrix_init_identity(&shear);
468 : 0 : shear.xy = -shear.xx * 0x6000L / 0x10000L;
469 : 0 : cairo_matrix_multiply(&m, &shear, &m);
470 : : }
471 : :
472 : 0 : cairo_set_font_matrix(cr, &m);
473 : 0 : cairo_show_glyphs(cr, &cairo_glyphs[nStartIndex], nLen);
474 : :
475 : : #if OSL_DEBUG_LEVEL > 2
476 : : //draw origin
477 : : cairo_save (cr);
478 : : cairo_rectangle (cr, cairo_glyphs[nStartIndex].x, cairo_glyphs[nStartIndex].y, 5, 5);
479 : : cairo_set_source_rgba (cr, 1, 0, 0, 0.80);
480 : : cairo_fill (cr);
481 : : cairo_restore (cr);
482 : : #endif
483 : :
484 : 0 : aI = aNext;
485 : : }
486 : :
487 : 0 : cairo_destroy(cr);
488 : : }
489 : :
490 : : //--------------------------------------------------------------------------
491 : :
492 : 0 : const ImplFontCharMap* X11SalGraphics::GetImplFontCharMap() const
493 : : {
494 : 0 : if( !mpServerFont[0] )
495 : 0 : return NULL;
496 : :
497 : 0 : const ImplFontCharMap* pIFCMap = mpServerFont[0]->GetImplFontCharMap();
498 : 0 : return pIFCMap;
499 : : }
500 : :
501 : 0 : bool X11SalGraphics::GetImplFontCapabilities(vcl::FontCapabilities &rGetImplFontCapabilities) const
502 : : {
503 : 0 : if (!mpServerFont[0])
504 : 0 : return false;
505 : 0 : return mpServerFont[0]->GetFontCapabilities(rGetImplFontCapabilities);
506 : : }
507 : :
508 : : // ----------------------------------------------------------------------------
509 : : //
510 : : // SalGraphics
511 : : //
512 : : // ----------------------------------------------------------------------------
513 : :
514 : 0 : sal_uInt16 X11SalGraphics::SetFont( FontSelectPattern *pEntry, int nFallbackLevel )
515 : : {
516 : 0 : sal_uInt16 nRetVal = 0;
517 : 0 : if( !setFont( pEntry, nFallbackLevel ) )
518 : 0 : nRetVal |= SAL_SETFONT_BADFONT;
519 : 0 : if( bPrinter_ || (mpServerFont[ nFallbackLevel ] != NULL) )
520 : 0 : nRetVal |= SAL_SETFONT_USEDRAWTEXTARRAY;
521 : 0 : return nRetVal;
522 : : }
523 : :
524 : : // ----------------------------------------------------------------------------
525 : :
526 : : void
527 : 0 : X11SalGraphics::SetTextColor( SalColor nSalColor )
528 : : {
529 : 0 : if( nTextColor_ != nSalColor )
530 : : {
531 : 0 : nTextColor_ = nSalColor;
532 : 0 : nTextPixel_ = GetPixel( nSalColor );
533 : 0 : bFontGC_ = sal_False;
534 : : }
535 : 0 : }
536 : :
537 : : // ----------------------------------------------------------------------------
538 : :
539 : 0 : bool X11SalGraphics::AddTempDevFont( ImplDevFontList* pFontList,
540 : : const rtl::OUString& rFileURL, const rtl::OUString& rFontName )
541 : : {
542 : : // inform PSP font manager
543 : 0 : rtl::OUString aUSystemPath;
544 : 0 : OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFileURL, aUSystemPath ) );
545 : 0 : rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
546 : 0 : OString aOFileName( OUStringToOString( aUSystemPath, aEncoding ) );
547 : 0 : psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
548 : 0 : std::vector<psp::fontID> aFontIds = rMgr.addFontFile( aOFileName );
549 : 0 : if( aFontIds.empty() )
550 : 0 : return false;
551 : :
552 : 0 : GlyphCache& rGC = X11GlyphCache::GetInstance();
553 : :
554 : 0 : for (std::vector<psp::fontID>::iterator aI = aFontIds.begin(), aEnd = aFontIds.end(); aI != aEnd; ++aI)
555 : : {
556 : : // prepare font data
557 : 0 : psp::FastPrintFontInfo aInfo;
558 : 0 : rMgr.getFontFastInfo( *aI, aInfo );
559 : 0 : aInfo.m_aFamilyName = rFontName;
560 : :
561 : : // inform glyph cache of new font
562 : 0 : ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
563 : 0 : aDFA.mnQuality += 5800;
564 : :
565 : 0 : int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
566 : :
567 : 0 : const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
568 : 0 : rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
569 : 0 : }
570 : :
571 : : // announce new font to device's font list
572 : 0 : rGC.AnnounceFonts( pFontList );
573 : 0 : return true;
574 : : }
575 : :
576 : : // ----------------------------------------------------------------------------
577 : :
578 : 0 : void X11SalGraphics::GetDevFontList( ImplDevFontList *pList )
579 : : {
580 : : // prepare the GlyphCache using psprint's font infos
581 : 0 : X11GlyphCache& rGC = X11GlyphCache::GetInstance();
582 : :
583 : 0 : psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
584 : 0 : ::std::list< psp::fontID > aList;
585 : 0 : ::std::list< psp::fontID >::iterator it;
586 : 0 : psp::FastPrintFontInfo aInfo;
587 : 0 : rMgr.getFontList( aList );
588 : 0 : for( it = aList.begin(); it != aList.end(); ++it )
589 : : {
590 : 0 : if( !rMgr.getFontFastInfo( *it, aInfo ) )
591 : 0 : continue;
592 : :
593 : : // the GlyphCache must not bother with builtin fonts because
594 : : // it cannot access or use them anyway
595 : 0 : if( aInfo.m_eType == psp::fonttype::Builtin )
596 : 0 : continue;
597 : :
598 : : // normalize face number to the GlyphCache
599 : 0 : int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
600 : :
601 : : // for fonts where extra kerning info can be provided on demand
602 : : // an ExtraKernInfo object is supplied
603 : 0 : const ExtraKernInfo* pExtraKernInfo = NULL;
604 : 0 : if( aInfo.m_eType == psp::fonttype::Type1 )
605 : 0 : pExtraKernInfo = new PspKernInfo( *it );
606 : :
607 : : // inform GlyphCache about this font provided by the PsPrint subsystem
608 : 0 : ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
609 : 0 : aDFA.mnQuality += 4096;
610 : 0 : const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
611 : 0 : rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA, pExtraKernInfo );
612 : 0 : }
613 : :
614 : : // announce glyphcache fonts
615 : 0 : rGC.AnnounceFonts( pList );
616 : :
617 : : // register platform specific font substitutions if available
618 : 0 : SalGenericInstance::RegisterFontSubstitutors( pList );
619 : :
620 : 0 : ImplGetSVData()->maGDIData.mbNativeFontConfig = true;
621 : 0 : }
622 : :
623 : : // ----------------------------------------------------------------------------
624 : :
625 : 0 : void X11SalGraphics::GetDevFontSubstList( OutputDevice* )
626 : : {
627 : : // no device specific font substitutions on X11 needed
628 : 0 : }
629 : :
630 : : // ----------------------------------------------------------------------------
631 : :
632 : 0 : void cairosubcallback(void* pPattern)
633 : : {
634 : 0 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
635 : 0 : const void* pFontOptions = rStyleSettings.GetCairoFontOptions();
636 : 0 : if( !pFontOptions )
637 : 0 : return;
638 : : cairo_ft_font_options_substitute(static_cast<const cairo_font_options_t*>(pFontOptions),
639 : 0 : static_cast<FcPattern*>(pPattern));
640 : : }
641 : :
642 : 0 : ImplFontOptions* GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize)
643 : : {
644 : 0 : psp::FastPrintFontInfo aInfo;
645 : :
646 : 0 : aInfo.m_aFamilyName = rFontAttributes.GetFamilyName();
647 : 0 : aInfo.m_eItalic = rFontAttributes.GetSlant();
648 : 0 : aInfo.m_eWeight = rFontAttributes.GetWeight();
649 : 0 : aInfo.m_eWidth = rFontAttributes.GetWidthType();
650 : :
651 : 0 : const psp::PrintFontManager& rPFM = psp::PrintFontManager::get();
652 : 0 : return rPFM.getFontOptions(aInfo, nSize, cairosubcallback);
653 : : }
654 : :
655 : : // ----------------------------------------------------------------------------
656 : :
657 : : void
658 : 0 : X11SalGraphics::GetFontMetric( ImplFontMetricData *pMetric, int nFallbackLevel )
659 : : {
660 : 0 : if( nFallbackLevel >= MAX_FALLBACK )
661 : 0 : return;
662 : :
663 : 0 : if( mpServerFont[nFallbackLevel] != NULL )
664 : : {
665 : : long rDummyFactor;
666 : 0 : mpServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor );
667 : : }
668 : : }
669 : :
670 : : // ---------------------------------------------------------------------------
671 : :
672 : : sal_uLong
673 : 0 : X11SalGraphics::GetKernPairs( sal_uLong nPairs, ImplKernPairData *pKernPairs )
674 : : {
675 : 0 : if( ! bPrinter_ )
676 : : {
677 : 0 : if( mpServerFont[0] != NULL )
678 : : {
679 : : ImplKernPairData* pTmpKernPairs;
680 : 0 : sal_uLong nGotPairs = mpServerFont[0]->GetKernPairs( &pTmpKernPairs );
681 : 0 : for( unsigned int i = 0; i < nPairs && i < nGotPairs; ++i )
682 : 0 : pKernPairs[ i ] = pTmpKernPairs[ i ];
683 : 0 : delete[] pTmpKernPairs;
684 : 0 : return nGotPairs;
685 : : }
686 : : }
687 : 0 : return 0;
688 : : }
689 : :
690 : : // ---------------------------------------------------------------------------
691 : :
692 : 0 : sal_Bool X11SalGraphics::GetGlyphBoundRect( sal_GlyphId nGlyphIndex, Rectangle& rRect )
693 : : {
694 : 0 : int nLevel = nGlyphIndex >> GF_FONTSHIFT;
695 : 0 : if( nLevel >= MAX_FALLBACK )
696 : 0 : return sal_False;
697 : :
698 : 0 : ServerFont* pSF = mpServerFont[ nLevel ];
699 : 0 : if( !pSF )
700 : 0 : return sal_False;
701 : :
702 : 0 : nGlyphIndex &= GF_IDXMASK;
703 : 0 : const GlyphMetric& rGM = pSF->GetGlyphMetric( nGlyphIndex );
704 : 0 : Rectangle aRect( rGM.GetOffset(), rGM.GetSize() );
705 : :
706 : 0 : if ( pSF->mnCos != 0x10000 && pSF->mnSin != 0 )
707 : : {
708 : 0 : double nCos = pSF->mnCos / 65536.0;
709 : 0 : double nSin = pSF->mnSin / 65536.0;
710 : 0 : rRect.Left() = nCos*aRect.Left() + nSin*aRect.Top();
711 : 0 : rRect.Top() = -nSin*aRect.Left() - nCos*aRect.Top();
712 : :
713 : 0 : rRect.Right() = nCos*aRect.Right() + nSin*aRect.Bottom();
714 : 0 : rRect.Bottom() = -nSin*aRect.Right() - nCos*aRect.Bottom();
715 : : }
716 : : else
717 : 0 : rRect = aRect;
718 : :
719 : 0 : return sal_True;
720 : : }
721 : :
722 : : // ---------------------------------------------------------------------------
723 : :
724 : 0 : sal_Bool X11SalGraphics::GetGlyphOutline( sal_GlyphId nGlyphIndex,
725 : : ::basegfx::B2DPolyPolygon& rPolyPoly )
726 : : {
727 : 0 : int nLevel = nGlyphIndex >> GF_FONTSHIFT;
728 : 0 : if( nLevel >= MAX_FALLBACK )
729 : 0 : return sal_False;
730 : :
731 : 0 : ServerFont* pSF = mpServerFont[ nLevel ];
732 : 0 : if( !pSF )
733 : 0 : return sal_False;
734 : :
735 : 0 : nGlyphIndex &= GF_IDXMASK;
736 : 0 : if( pSF->GetGlyphOutline( nGlyphIndex, rPolyPoly ) )
737 : 0 : return sal_True;
738 : :
739 : 0 : return sal_False;
740 : : }
741 : :
742 : : //--------------------------------------------------------------------------
743 : :
744 : 0 : SalLayout* X11SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
745 : : {
746 : 0 : SalLayout* pLayout = NULL;
747 : :
748 : 0 : if( mpServerFont[ nFallbackLevel ]
749 : 0 : && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
750 : : {
751 : : #ifdef ENABLE_GRAPHITE
752 : : // Is this a Graphite font?
753 : 0 : if (!bDisableGraphite_ &&
754 : 0 : GraphiteServerFontLayout::IsGraphiteEnabledFont(*mpServerFont[nFallbackLevel]))
755 : : {
756 : 0 : pLayout = new GraphiteServerFontLayout(*mpServerFont[nFallbackLevel]);
757 : : }
758 : : else
759 : : #endif
760 : 0 : pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] );
761 : : }
762 : :
763 : 0 : return pLayout;
764 : : }
765 : :
766 : : //--------------------------------------------------------------------------
767 : :
768 : 0 : SystemFontData X11SalGraphics::GetSysFontData( int nFallbacklevel ) const
769 : : {
770 : 0 : SystemFontData aSysFontData;
771 : 0 : aSysFontData.nSize = sizeof( SystemFontData );
772 : 0 : aSysFontData.nFontId = 0;
773 : :
774 : 0 : if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
775 : 0 : if (nFallbacklevel < 0 ) nFallbacklevel = 0;
776 : :
777 : 0 : if (mpServerFont[nFallbacklevel] != NULL)
778 : : {
779 : 0 : ServerFont* rFont = mpServerFont[nFallbacklevel];
780 : 0 : aSysFontData.nFontId = rFont->GetFtFace();
781 : 0 : aSysFontData.nFontFlags = rFont->GetLoadFlags();
782 : 0 : aSysFontData.bFakeBold = rFont->NeedsArtificialBold();
783 : 0 : aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic();
784 : 0 : aSysFontData.bAntialias = rFont->GetAntialiasAdvice();
785 : 0 : aSysFontData.bVerticalCharacterType = rFont->GetFontSelData().mbVertical;
786 : : }
787 : :
788 : 0 : return aSysFontData;
789 : : }
790 : :
791 : : //--------------------------------------------------------------------------
792 : :
793 : 0 : sal_Bool X11SalGraphics::CreateFontSubset(
794 : : const rtl::OUString& rToFile,
795 : : const PhysicalFontFace* pFont,
796 : : sal_Int32* pGlyphIDs,
797 : : sal_uInt8* pEncoding,
798 : : sal_Int32* pWidths,
799 : : int nGlyphCount,
800 : : FontSubsetInfo& rInfo
801 : : )
802 : : {
803 : : // in this context the pFont->GetFontId() is a valid PSP
804 : : // font since they are the only ones left after the PDF
805 : : // export has filtered its list of subsettable fonts (for
806 : : // which this method was created). The correct way would
807 : : // be to have the GlyphCache search for the PhysicalFontFace pFont
808 : 0 : psp::fontID aFont = pFont->GetFontId();
809 : :
810 : 0 : psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
811 : : bool bSuccess = rMgr.createFontSubset( rInfo,
812 : : aFont,
813 : : rToFile,
814 : : pGlyphIDs,
815 : : pEncoding,
816 : : pWidths,
817 : 0 : nGlyphCount );
818 : 0 : return bSuccess;
819 : : }
820 : :
821 : : //--------------------------------------------------------------------------
822 : :
823 : 0 : const void* X11SalGraphics::GetEmbedFontData( const PhysicalFontFace* pFont, const sal_Ucs* pUnicodes, sal_Int32* pWidths, FontSubsetInfo& rInfo, long* pDataLen )
824 : : {
825 : : // in this context the pFont->GetFontId() is a valid PSP
826 : : // font since they are the only ones left after the PDF
827 : : // export has filtered its list of subsettable fonts (for
828 : : // which this method was created). The correct way would
829 : : // be to have the GlyphCache search for the PhysicalFontFace pFont
830 : 0 : psp::fontID aFont = pFont->GetFontId();
831 : 0 : return GenPspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
832 : : }
833 : :
834 : : //--------------------------------------------------------------------------
835 : :
836 : 0 : void X11SalGraphics::FreeEmbedFontData( const void* pData, long nLen )
837 : : {
838 : 0 : GenPspGraphics::DoFreeEmbedFontData( pData, nLen );
839 : 0 : }
840 : :
841 : : //--------------------------------------------------------------------------
842 : :
843 : 0 : const Ucs2SIntMap* X11SalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
844 : : {
845 : : // in this context the pFont->GetFontId() is a valid PSP
846 : : // font since they are the only ones left after the PDF
847 : : // export has filtered its list of subsettable fonts (for
848 : : // which this method was created). The correct way would
849 : : // be to have the GlyphCache search for the PhysicalFontFace pFont
850 : 0 : psp::fontID aFont = pFont->GetFontId();
851 : 0 : return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
852 : : }
853 : :
854 : : //--------------------------------------------------------------------------
855 : :
856 : 0 : void X11SalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont,
857 : : bool bVertical,
858 : : Int32Vector& rWidths,
859 : : Ucs2UIntMap& rUnicodeEnc )
860 : : {
861 : : // in this context the pFont->GetFontId() is a valid PSP
862 : : // font since they are the only ones left after the PDF
863 : : // export has filtered its list of subsettable fonts (for
864 : : // which this method was created). The correct way would
865 : : // be to have the GlyphCache search for the PhysicalFontFace pFont
866 : 0 : psp::fontID aFont = pFont->GetFontId();
867 : 0 : GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
868 : 0 : }
869 : :
870 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|