--- vcl.precairo/inc/vcl/glyphcache.hxx 2008-01-21 15:29:34.000000000 +0000 +++ vcl.precairo/inc/vcl/glyphcache.hxx 2008-01-21 19:26:06.000000000 +0000 @@ -210,6 +210,9 @@ int GetExtInfo() { return mnExtInfo; } void* GetExtPointer() { return mpExtData; } + virtual void* GetFtFace() const { return 0; } + virtual int GetLoadFlags() const { return 0; } + protected: friend class GlyphCache; friend class ServerFontLayout; --- vcl.precairo/source/glyphs/gcach_ftyp.hxx 2008-01-21 15:29:27.000000000 +0000 +++ vcl.precairo/source/glyphs/gcach_ftyp.hxx 2008-01-21 19:25:43.000000000 +0000 @@ -200,6 +200,9 @@ int GetEmUnits() const; const FT_Size_Metrics& GetMetricsFT() const { return maSizeFT->metrics; } + virtual void* GetFtFace() const { return maFaceFT; } + virtual int GetLoadFlags() const { return mnLoadFlags; } + protected: friend class GlyphCache; --- vcl.precairo/unx/inc/salgdi.h 2008-01-21 15:29:33.000000000 +0000 +++ vcl.precairo/unx/inc/salgdi.h 2008-01-22 14:19:55.000000000 +0000 @@ -198,6 +198,7 @@ void DrawServerSimpleFontString( const ServerFontLayout& ); void DrawServerAAFontString( const ServerFontLayout& ); bool DrawServerAAForcedString( const ServerFontLayout& ); + void DrawCairoAAFontString( const ServerFontLayout& ); void freeResources(); public: --- vcl.precairo/unx/source/gdi/salgdi3.cxx 2008-01-21 15:29:33.000000000 +0000 +++ vcl.precairo/unx/source/gdi/salgdi3.cxx 2008-01-22 14:21:16.000000000 +0000 @@ -123,6 +123,22 @@ #include +struct cairo_surface_t; +struct cairo_t; +struct cairo_font_face_t; +typedef void* FT_Face; +struct cairo_matrix_t { + double xx; double yx; + double xy; double yy; + double x0; double y0; +}; +struct cairo_glyph_t +{ + unsigned long index; + double x; + double y; +}; + using namespace rtl; // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -734,6 +750,203 @@ } //-------------------------------------------------------------------------- +namespace { + +class CairoWrapper +{ +private: + bool mbIsValid; + + cairo_surface_t* (*mp_xlib_surface_create)(Display *, Drawable , Visual *, int , int ); + void (*mp_surface_destroy)(cairo_surface_t *); + cairo_t* (*mp_create)(cairo_surface_t *); + void (*mp_destroy)(cairo_t*); + void (*mp_clip)(cairo_t*); + void (*mp_rectangle)(cairo_t*, double, double, double, double); + cairo_font_face_t * (*mp_ft_font_face_create_for_ft_face)(FT_Face, int); + void (*mp_set_font_face)(cairo_t *, cairo_font_face_t *); + void (*mp_font_face_destroy)(cairo_font_face_t *); + void (*mp_matrix_init_scale)(cairo_matrix_t *, double, double); + void (*mp_matrix_rotate)(cairo_matrix_t *, double); + void (*mp_set_font_matrix)(cairo_t *, const cairo_matrix_t *); + void (*mp_show_glyphs)(cairo_t *, const cairo_glyph_t *, int ); + void (*mp_set_source_rgb)(cairo_t *, double , double , double ); + + oslGenericFunction loadSymbol( const char* ); + CairoWrapper(); +public: + static CairoWrapper& get(); + bool isValid() const { return mbIsValid; } + + cairo_surface_t* xlib_surface_create(Display *pDisplay, Drawable drawable, Visual *pVisual, int width, int height) + { return (*mp_xlib_surface_create)(pDisplay, drawable, pVisual, width, height); } + void surface_destroy(cairo_surface_t *surface) { (*mp_surface_destroy)(surface); } + cairo_t* create(cairo_surface_t *surface) { return (*mp_create)(surface); } + void destroy(cairo_t *cr) { (*mp_destroy)(cr); } + void clip(cairo_t *cr) { (*mp_clip)(cr); } + void rectangle(cairo_t *cr, double x, double y, double width, double height) + { (*mp_rectangle)(cr, x, y, width, height); } + cairo_font_face_t* ft_font_face_create_for_ft_face(FT_Face face, int load_flags) + { return (*mp_ft_font_face_create_for_ft_face)(face, load_flags); } + void set_font_face(cairo_t *cr, cairo_font_face_t *font_face) + { (*mp_set_font_face)(cr, font_face); } + void font_face_destroy(cairo_font_face_t *font_face) + { (*mp_font_face_destroy)(font_face); } + void matrix_init_scale(cairo_matrix_t *matrix, double sx, double sy) + { (*mp_matrix_init_scale)(matrix, sx, sy); } + void matrix_rotate(cairo_matrix_t *matrix, double radians) + { (*mp_matrix_rotate)(matrix, radians); } + void set_font_matrix(cairo_t *cr, const cairo_matrix_t *matrix) + { (*mp_set_font_matrix)(cr, matrix); } + void show_glyphs(cairo_t *cr, const cairo_glyph_t *glyphs, int no_glyphs) + { (*mp_show_glyphs)(cr, glyphs, no_glyphs); } + void set_source_rgb(cairo_t *cr, double red, double green, double blue) + { (*mp_set_source_rgb)(cr, red, green, blue); } +}; + +static CairoWrapper* pOneInstance = NULL; + +CairoWrapper& CairoWrapper::get() +{ + if( ! pOneInstance ) + pOneInstance = new CairoWrapper(); + return *pOneInstance; +} + +oslGenericFunction CairoWrapper::loadSymbol( const char* pSymbol ) +{ + OUString aSym( OUString::createFromAscii( pSymbol ) ); + oslGenericFunction pSym = osl_getFunctionSymbol( NULL, aSym.pData ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "%s %s\n", pSymbol, pSym ? "found" : "not found" ); +#endif + return pSym; +} + +CairoWrapper::CairoWrapper() : mbIsValid(false) +{ + static const char* pDisableCairoText = getenv( "SAL_DISABLE_CAIROTEXT" ); + if( pDisableCairoText && (pDisableCairoText[0] == '1') ) + return; + + mp_xlib_surface_create = (cairo_surface_t* (*)(Display *, Drawable , Visual *, int , int )) + loadSymbol( "cairo_xlib_surface_create" ); + mp_surface_destroy = (void(*)(cairo_surface_t*)) + loadSymbol( "cairo_surface_destroy" ); + mp_create = (cairo_t*(*)(cairo_surface_t*)) + loadSymbol( "cairo_create" ); + mp_destroy = (void(*)(cairo_t*)) + loadSymbol( "cairo_destroy" ); + mp_clip = (void(*)(cairo_t*)) + loadSymbol( "cairo_clip" ); + mp_rectangle = (void(*)(cairo_t*, double, double, double, double)) + loadSymbol( "cairo_rectangle" ); + mp_ft_font_face_create_for_ft_face = (cairo_font_face_t * (*)(FT_Face, int)) + loadSymbol( "cairo_ft_font_face_create_for_ft_face" ); + mp_set_font_face = (void (*)(cairo_t *, cairo_font_face_t *)) + loadSymbol( "cairo_set_font_face" ); + mp_font_face_destroy = (void (*)(cairo_font_face_t *)) + loadSymbol( "cairo_font_face_destroy" ); + mp_matrix_init_scale = (void (*)(cairo_matrix_t *, double, double)) + loadSymbol( "cairo_matrix_init_scale" ); + mp_matrix_rotate = (void (*)(cairo_matrix_t *, double)) + loadSymbol( "cairo_matrix_rotate" ); + mp_set_font_matrix = (void (*)(cairo_t *, const cairo_matrix_t *)) + loadSymbol( "cairo_set_font_matrix" ); + mp_show_glyphs = (void (*)(cairo_t *, const cairo_glyph_t *, int )) + loadSymbol( "cairo_show_glyphs" ); + mp_set_source_rgb = (void (*)(cairo_t *, double , double , double )) + loadSymbol( "cairo_set_source_rgb" ); + + mbIsValid = + ( + mp_xlib_surface_create && + mp_surface_destroy && + mp_create && + mp_destroy && + mp_clip && + mp_rectangle && + mp_ft_font_face_create_for_ft_face && + mp_set_font_face && + mp_font_face_destroy && + mp_matrix_init_scale && + mp_matrix_rotate && + mp_set_font_matrix && + mp_show_glyphs && + mp_set_source_rgb + ); + if (!mbIsValid) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "not all needed symbols were found in libfontconfig\n" ); +#endif + } +} + +} //namespace + +void X11SalGraphics::DrawCairoAAFontString( const ServerFontLayout& rLayout ) +{ + Display* pDisplay = GetXDisplay(); + Visual* pVisual = GetDisplay()->GetVisual( GetScreenNumber() ).GetVisual(); + CairoWrapper &rCairo = CairoWrapper::get(); + + cairo_surface_t *surface = rCairo.xlib_surface_create (pDisplay, + hDrawable_, pVisual, 1, 1); + + cairo_t *cr = rCairo.create (surface); + rCairo.surface_destroy (surface); + + if( pClipRegion_ && !XEmptyRegion( pClipRegion_ ) ) + { + XRectangle aXRect; + XClipBox( pClipRegion_, &aXRect ); + rCairo.rectangle(cr, aXRect.x, aXRect.y, aXRect.width, aXRect.height); + rCairo.clip(cr); + } + + rCairo.set_source_rgb(cr, + SALCOLOR_RED(nTextColor_)/255.0, + SALCOLOR_GREEN(nTextColor_)/255.0, + SALCOLOR_BLUE(nTextColor_)/255.0); + + ServerFont& rFont = rLayout.GetServerFont(); + + cairo_font_face_t* font_face = + rCairo.ft_font_face_create_for_ft_face(rFont.GetFtFace(), rFont.GetLoadFlags()); + + rCairo.set_font_face(cr, font_face); + + cairo_matrix_t m; + const ImplFontSelectData& rFSD = rFont.GetFontSelData(); + int nWidth = rFSD.mnWidth ? rFSD.mnWidth : rFSD.mnHeight; + rCairo.matrix_init_scale(&m, nWidth, rFSD.mnHeight); + if (rLayout.GetOrientation()) + rCairo.matrix_rotate(&m, (3600 - rLayout.GetOrientation()) * M_PI / 1800.0); + rCairo.set_font_matrix(cr, &m); + + std::vector cairo_glyphs; + sal_Int32 nGlyph; + Point aPos; + int nStart = 0; + while (rLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart )) + { + cairo_glyph_t aGlyph; + aGlyph.index = nGlyph; + aGlyph.x = aPos.X(); + aGlyph.y = aPos.Y(); + cairo_glyphs.push_back(aGlyph); + } + + if (!cairo_glyphs.empty()) + rCairo.show_glyphs (cr, &cairo_glyphs[0], cairo_glyphs.size()); + + rCairo.font_face_destroy(font_face); + + rCairo.destroy (cr); +} + +//-------------------------------------------------------------------------- void X11SalGraphics::DrawServerAAFontString( const ServerFontLayout& rLayout ) { @@ -1111,15 +1324,20 @@ // draw complex text ServerFont& rFont = rLayout.GetServerFont(); - X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer(); - if( rGlyphPeer.GetGlyphSet( rFont, m_nScreen ) ) - DrawServerAAFontString( rLayout ); + if (rFont.GetFtFace() && CairoWrapper::get().isValid()) + DrawCairoAAFontString( rLayout ); + else + { + X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer(); + if( rGlyphPeer.GetGlyphSet( rFont, m_nScreen ) ) + DrawServerAAFontString( rLayout ); #ifndef MACOSX /* ignore X11 fonts on MACOSX */ - else if( !rGlyphPeer.ForcedAntialiasing( rFont, m_nScreen ) ) - DrawServerSimpleFontString( rLayout ); + else if( !rGlyphPeer.ForcedAntialiasing( rFont, m_nScreen ) ) + DrawServerSimpleFontString( rLayout ); #endif // MACOSX - else - DrawServerAAForcedString( rLayout ); + else + DrawServerAAForcedString( rLayout ); + } } //--------------------------------------------------------------------------