1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // Description: Implements the Graphite interfaces with access to the 29*cdf0e10cSrcweir // platform's font and graphics systems. 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 32*cdf0e10cSrcweir #include "precompiled_vcl.hxx" 33*cdf0e10cSrcweir 34*cdf0e10cSrcweir // We need this to enable namespace support in libgrengine headers. 35*cdf0e10cSrcweir #define GR_NAMESPACE 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir // Header files 38*cdf0e10cSrcweir // 39*cdf0e10cSrcweir // Standard Library 40*cdf0e10cSrcweir #include <string> 41*cdf0e10cSrcweir #include <cassert> 42*cdf0e10cSrcweir // Libraries 43*cdf0e10cSrcweir #include <rtl/string.hxx> 44*cdf0e10cSrcweir #include <rtl/ustring.hxx> 45*cdf0e10cSrcweir #include <i18npool/mslangid.hxx> 46*cdf0e10cSrcweir // Platform 47*cdf0e10cSrcweir #ifndef WNT 48*cdf0e10cSrcweir #include <unx/saldisp.hxx> 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir #include <salgdi.hxx> 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir #include <freetype/ftsynth.h> 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir // Module 55*cdf0e10cSrcweir #include "gcach_ftyp.hxx" 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir #include <graphite_features.hxx> 58*cdf0e10cSrcweir #include <graphite_adaptors.hxx> 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir // Module private type definitions and forward declarations. 61*cdf0e10cSrcweir // 62*cdf0e10cSrcweir using gr::GrResult; 63*cdf0e10cSrcweir namespace 64*cdf0e10cSrcweir { 65*cdf0e10cSrcweir inline float from_hinted(const int x) { 66*cdf0e10cSrcweir return static_cast<float>(x + 32) / 64.0; 67*cdf0e10cSrcweir } 68*cdf0e10cSrcweir typedef std::hash_map<long,bool> SilfMap; 69*cdf0e10cSrcweir SilfMap sSilfMap; 70*cdf0e10cSrcweir } 71*cdf0e10cSrcweir extern FT_Error (*pFTEmbolden)(FT_GlyphSlot); 72*cdf0e10cSrcweir extern FT_Error (*pFTOblique)(FT_GlyphSlot); 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir // class CharacterRenderProperties implentation. 75*cdf0e10cSrcweir // 76*cdf0e10cSrcweir FontProperties::FontProperties(const FreetypeServerFont &font) throw() 77*cdf0e10cSrcweir { 78*cdf0e10cSrcweir clrFore = gr::kclrBlack; 79*cdf0e10cSrcweir clrBack = gr::kclrTransparent; 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir pixHeight = from_hinted(font.GetMetricsFT().height); 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir switch (font.GetFontSelData().meWeight) 84*cdf0e10cSrcweir { 85*cdf0e10cSrcweir case WEIGHT_SEMIBOLD: case WEIGHT_BOLD: 86*cdf0e10cSrcweir case WEIGHT_ULTRABOLD: case WEIGHT_BLACK: 87*cdf0e10cSrcweir fBold = true; 88*cdf0e10cSrcweir break; 89*cdf0e10cSrcweir default : 90*cdf0e10cSrcweir fBold = false; 91*cdf0e10cSrcweir } 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir switch (font.GetFontSelData().meItalic) 94*cdf0e10cSrcweir { 95*cdf0e10cSrcweir case ITALIC_NORMAL: case ITALIC_OBLIQUE: 96*cdf0e10cSrcweir fItalic = true; 97*cdf0e10cSrcweir break; 98*cdf0e10cSrcweir default : 99*cdf0e10cSrcweir fItalic = false; 100*cdf0e10cSrcweir } 101*cdf0e10cSrcweir 102*cdf0e10cSrcweir // Get the font name, but prefix with file name hash in case 103*cdf0e10cSrcweir // there are 2 fonts on the system with the same face name 104*cdf0e10cSrcweir sal_Int32 nHashCode = font.GetFontFileName()->hashCode(); 105*cdf0e10cSrcweir ::rtl::OUStringBuffer nHashFaceName; 106*cdf0e10cSrcweir nHashFaceName.append(nHashCode, 16); 107*cdf0e10cSrcweir const sal_Unicode * name = font.GetFontSelData().maName.GetBuffer(); 108*cdf0e10cSrcweir nHashFaceName.append(name); 109*cdf0e10cSrcweir 110*cdf0e10cSrcweir const size_t name_sz = std::min(sizeof szFaceName/sizeof(wchar_t)-1, 111*cdf0e10cSrcweir static_cast<size_t>(nHashFaceName.getLength())); 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir std::copy(nHashFaceName.getStr(), nHashFaceName.getStr() + name_sz, szFaceName); 114*cdf0e10cSrcweir szFaceName[name_sz] = '\0'; 115*cdf0e10cSrcweir } 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir // class GraphiteFontAdaptor implementaion. 118*cdf0e10cSrcweir // 119*cdf0e10cSrcweir GraphiteFontAdaptor::GraphiteFontAdaptor(ServerFont & sfont, const sal_Int32 dpiX, const sal_Int32 dpiY) 120*cdf0e10cSrcweir : mrFont(static_cast<FreetypeServerFont &>(sfont)), 121*cdf0e10cSrcweir maFontProperties(static_cast<FreetypeServerFont &>(sfont)), 122*cdf0e10cSrcweir mnDpiX(dpiX), 123*cdf0e10cSrcweir mnDpiY(dpiY), 124*cdf0e10cSrcweir mfAscent(from_hinted(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().ascender)), 125*cdf0e10cSrcweir mfDescent(from_hinted(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().descender)), 126*cdf0e10cSrcweir mfEmUnits(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().y_ppem), 127*cdf0e10cSrcweir mpFeatures(NULL) 128*cdf0e10cSrcweir { 129*cdf0e10cSrcweir const rtl::OString aLang = MsLangId::convertLanguageToIsoByteString( sfont.GetFontSelData().meLanguage ); 130*cdf0e10cSrcweir rtl::OString name = rtl::OUStringToOString( 131*cdf0e10cSrcweir sfont.GetFontSelData().maTargetName, RTL_TEXTENCODING_UTF8 ); 132*cdf0e10cSrcweir #ifdef DEBUG 133*cdf0e10cSrcweir printf("GraphiteFontAdaptor %lx %s italic=%u bold=%u\n", (long)this, name.getStr(), 134*cdf0e10cSrcweir maFontProperties.fItalic, maFontProperties.fBold); 135*cdf0e10cSrcweir #endif 136*cdf0e10cSrcweir sal_Int32 nFeat = name.indexOf(grutils::GrFeatureParser::FEAT_PREFIX) + 1; 137*cdf0e10cSrcweir if (nFeat > 0) 138*cdf0e10cSrcweir { 139*cdf0e10cSrcweir rtl::OString aFeat = name.copy(nFeat, name.getLength() - nFeat); 140*cdf0e10cSrcweir mpFeatures = new grutils::GrFeatureParser(*this, aFeat.getStr(), aLang.getStr()); 141*cdf0e10cSrcweir #ifdef DEBUG 142*cdf0e10cSrcweir printf("GraphiteFontAdaptor %s/%s/%s %x language %d features %d errors\n", 143*cdf0e10cSrcweir rtl::OUStringToOString( sfont.GetFontSelData().maName, 144*cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 ).getStr(), 145*cdf0e10cSrcweir rtl::OUStringToOString( sfont.GetFontSelData().maTargetName, 146*cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 ).getStr(), 147*cdf0e10cSrcweir rtl::OUStringToOString( sfont.GetFontSelData().maSearchName, 148*cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 ).getStr(), 149*cdf0e10cSrcweir sfont.GetFontSelData().meLanguage, 150*cdf0e10cSrcweir (int)mpFeatures->getFontFeatures(NULL), mpFeatures->parseErrors()); 151*cdf0e10cSrcweir #endif 152*cdf0e10cSrcweir } 153*cdf0e10cSrcweir else 154*cdf0e10cSrcweir { 155*cdf0e10cSrcweir mpFeatures = new grutils::GrFeatureParser(*this, aLang.getStr()); 156*cdf0e10cSrcweir } 157*cdf0e10cSrcweir } 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir GraphiteFontAdaptor::GraphiteFontAdaptor(const GraphiteFontAdaptor &rhs) throw() 160*cdf0e10cSrcweir : Font(rhs), 161*cdf0e10cSrcweir mrFont (rhs.mrFont), maFontProperties(rhs.maFontProperties), 162*cdf0e10cSrcweir mnDpiX(rhs.mnDpiX), mnDpiY(rhs.mnDpiY), 163*cdf0e10cSrcweir mfAscent(rhs.mfAscent), mfDescent(rhs.mfDescent), mfEmUnits(rhs.mfEmUnits), 164*cdf0e10cSrcweir mpFeatures(NULL) 165*cdf0e10cSrcweir { 166*cdf0e10cSrcweir if (rhs.mpFeatures) mpFeatures = new grutils::GrFeatureParser(*(rhs.mpFeatures)); 167*cdf0e10cSrcweir } 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir GraphiteFontAdaptor::~GraphiteFontAdaptor() throw() 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir maGlyphMetricMap.clear(); 173*cdf0e10cSrcweir if (mpFeatures) delete mpFeatures; 174*cdf0e10cSrcweir mpFeatures = NULL; 175*cdf0e10cSrcweir } 176*cdf0e10cSrcweir 177*cdf0e10cSrcweir void GraphiteFontAdaptor::UniqueCacheInfo(ext_std::wstring & face_name_out, bool & bold_out, bool & italic_out) 178*cdf0e10cSrcweir { 179*cdf0e10cSrcweir face_name_out = maFontProperties.szFaceName; 180*cdf0e10cSrcweir bold_out = maFontProperties.fBold; 181*cdf0e10cSrcweir italic_out = maFontProperties.fItalic; 182*cdf0e10cSrcweir } 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir bool GraphiteFontAdaptor::IsGraphiteEnabledFont(ServerFont & font) throw() 185*cdf0e10cSrcweir { 186*cdf0e10cSrcweir // NOTE: this assumes that the same FTFace pointer won't be reused, 187*cdf0e10cSrcweir // so FtFontInfo::ReleaseFaceFT must only be called at shutdown. 188*cdf0e10cSrcweir FreetypeServerFont & aFtFont = dynamic_cast<FreetypeServerFont &>(font); 189*cdf0e10cSrcweir FT_Face aFace = reinterpret_cast<FT_FaceRec_*>(aFtFont.GetFtFace()); 190*cdf0e10cSrcweir SilfMap::iterator i = sSilfMap.find(reinterpret_cast<long>(aFace)); 191*cdf0e10cSrcweir if (i != sSilfMap.end()) 192*cdf0e10cSrcweir { 193*cdf0e10cSrcweir #ifdef DEBUG 194*cdf0e10cSrcweir if (static_cast<bool>(aFtFont.GetTable("Silf", 0)) != (*i).second) 195*cdf0e10cSrcweir printf("Silf cache font mismatch\n"); 196*cdf0e10cSrcweir #endif 197*cdf0e10cSrcweir return (*i).second; 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir bool bHasSilf = aFtFont.GetTable("Silf", 0); 200*cdf0e10cSrcweir sSilfMap[reinterpret_cast<long>(aFace)] = bHasSilf; 201*cdf0e10cSrcweir return bHasSilf; 202*cdf0e10cSrcweir } 203*cdf0e10cSrcweir 204*cdf0e10cSrcweir 205*cdf0e10cSrcweir gr::Font * GraphiteFontAdaptor::copyThis() { 206*cdf0e10cSrcweir return new GraphiteFontAdaptor(*this); 207*cdf0e10cSrcweir } 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir 210*cdf0e10cSrcweir unsigned int GraphiteFontAdaptor::getDPIx() { 211*cdf0e10cSrcweir return mnDpiX; 212*cdf0e10cSrcweir } 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir 215*cdf0e10cSrcweir unsigned int GraphiteFontAdaptor::getDPIy() { 216*cdf0e10cSrcweir return mnDpiY; 217*cdf0e10cSrcweir } 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir 220*cdf0e10cSrcweir float GraphiteFontAdaptor::ascent() { 221*cdf0e10cSrcweir return mfAscent; 222*cdf0e10cSrcweir } 223*cdf0e10cSrcweir 224*cdf0e10cSrcweir 225*cdf0e10cSrcweir float GraphiteFontAdaptor::descent() { 226*cdf0e10cSrcweir return mfDescent; 227*cdf0e10cSrcweir } 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir bool GraphiteFontAdaptor::bold() { 231*cdf0e10cSrcweir return maFontProperties.fBold; 232*cdf0e10cSrcweir } 233*cdf0e10cSrcweir 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir bool GraphiteFontAdaptor::italic() { 236*cdf0e10cSrcweir return maFontProperties.fItalic; 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir 240*cdf0e10cSrcweir float GraphiteFontAdaptor::height() { 241*cdf0e10cSrcweir return maFontProperties.pixHeight; 242*cdf0e10cSrcweir } 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir 245*cdf0e10cSrcweir void GraphiteFontAdaptor::getFontMetrics(float * ascent_out, float * descent_out, float * em_square_out) { 246*cdf0e10cSrcweir if (ascent_out) *ascent_out = mfAscent; 247*cdf0e10cSrcweir if (descent_out) *descent_out = mfDescent; 248*cdf0e10cSrcweir if (em_square_out) *em_square_out = mfEmUnits; 249*cdf0e10cSrcweir } 250*cdf0e10cSrcweir 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir const void * GraphiteFontAdaptor::getTable(gr::fontTableId32 table_id, size_t * buffer_sz) 253*cdf0e10cSrcweir { 254*cdf0e10cSrcweir char tag_name[5] = {char(table_id >> 24), char(table_id >> 16), char(table_id >> 8), char(table_id), 0}; 255*cdf0e10cSrcweir sal_uLong temp = *buffer_sz; 256*cdf0e10cSrcweir 257*cdf0e10cSrcweir const void * const tbl_buf = static_cast<FreetypeServerFont &>(mrFont).GetTable(tag_name, &temp); 258*cdf0e10cSrcweir *buffer_sz = temp; 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir return tbl_buf; 261*cdf0e10cSrcweir } 262*cdf0e10cSrcweir 263*cdf0e10cSrcweir #define fix26_6(x) (x >> 6) + (x & 32 ? (x > 0 ? 1 : 0) : (x < 0 ? -1 : 0)) 264*cdf0e10cSrcweir 265*cdf0e10cSrcweir // Return the glyph's metrics in pixels. 266*cdf0e10cSrcweir void GraphiteFontAdaptor::getGlyphMetrics(gr::gid16 nGlyphId, gr::Rect & aBounding, gr::Point & advances) 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir // There used to be problems when orientation was set however, this no 269*cdf0e10cSrcweir // longer seems to be the case and the Glyph Metric cache in 270*cdf0e10cSrcweir // FreetypeServerFont is more efficient since it lasts between calls to VCL 271*cdf0e10cSrcweir #if 1 272*cdf0e10cSrcweir const GlyphMetric & metric = mrFont.GetGlyphMetric(nGlyphId); 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir aBounding.right = aBounding.left = metric.GetOffset().X(); 275*cdf0e10cSrcweir aBounding.bottom = aBounding.top = -metric.GetOffset().Y(); 276*cdf0e10cSrcweir aBounding.right += metric.GetSize().Width(); 277*cdf0e10cSrcweir aBounding.bottom -= metric.GetSize().Height(); 278*cdf0e10cSrcweir 279*cdf0e10cSrcweir advances.x = metric.GetDelta().X(); 280*cdf0e10cSrcweir advances.y = -metric.GetDelta().Y(); 281*cdf0e10cSrcweir 282*cdf0e10cSrcweir #else 283*cdf0e10cSrcweir // The problem with the code below is that the cache only lasts 284*cdf0e10cSrcweir // as long as the life time of the GraphiteFontAdaptor, which 285*cdf0e10cSrcweir // is created once per call to X11SalGraphics::GetTextLayout 286*cdf0e10cSrcweir GlyphMetricMap::const_iterator gm_itr = maGlyphMetricMap.find(nGlyphId); 287*cdf0e10cSrcweir if (gm_itr != maGlyphMetricMap.end()) 288*cdf0e10cSrcweir { 289*cdf0e10cSrcweir // We've cached the results from last time. 290*cdf0e10cSrcweir aBounding = gm_itr->second.first; 291*cdf0e10cSrcweir advances = gm_itr->second.second; 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir else 294*cdf0e10cSrcweir { 295*cdf0e10cSrcweir // We need to look up the glyph. 296*cdf0e10cSrcweir FT_Int nLoadFlags = mrFont.GetLoadFlags(); 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir FT_Face aFace = reinterpret_cast<FT_Face>(mrFont.GetFtFace()); 299*cdf0e10cSrcweir if (!aFace) 300*cdf0e10cSrcweir { 301*cdf0e10cSrcweir aBounding.top = aBounding.bottom = aBounding.left = aBounding.right = 0; 302*cdf0e10cSrcweir advances.x = advances.y = 0; 303*cdf0e10cSrcweir return; 304*cdf0e10cSrcweir } 305*cdf0e10cSrcweir FT_Error aStatus = -1; 306*cdf0e10cSrcweir aStatus = FT_Load_Glyph(aFace, nGlyphId, nLoadFlags); 307*cdf0e10cSrcweir if( aStatus != FT_Err_Ok || (!aFace->glyph)) 308*cdf0e10cSrcweir { 309*cdf0e10cSrcweir aBounding.top = aBounding.bottom = aBounding.left = aBounding.right = 0; 310*cdf0e10cSrcweir advances.x = advances.y = 0; 311*cdf0e10cSrcweir return; 312*cdf0e10cSrcweir } 313*cdf0e10cSrcweir // check whether we need synthetic bold/italic otherwise metric is wrong 314*cdf0e10cSrcweir if (mrFont.NeedsArtificialBold() && pFTEmbolden) 315*cdf0e10cSrcweir (*pFTEmbolden)(aFace->glyph); 316*cdf0e10cSrcweir 317*cdf0e10cSrcweir if (mrFont.NeedsArtificialItalic() && pFTOblique) 318*cdf0e10cSrcweir (*pFTOblique)(aFace->glyph); 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir const FT_Glyph_Metrics &gm = aFace->glyph->metrics; 321*cdf0e10cSrcweir 322*cdf0e10cSrcweir // Fill out the bounding box an advances. 323*cdf0e10cSrcweir aBounding.top = aBounding.bottom = fix26_6(gm.horiBearingY); 324*cdf0e10cSrcweir aBounding.bottom -= fix26_6(gm.height); 325*cdf0e10cSrcweir aBounding.left = aBounding.right = fix26_6(gm.horiBearingX); 326*cdf0e10cSrcweir aBounding.right += fix26_6(gm.width); 327*cdf0e10cSrcweir advances.x = fix26_6(gm.horiAdvance); 328*cdf0e10cSrcweir advances.y = 0; 329*cdf0e10cSrcweir 330*cdf0e10cSrcweir // Now add an entry to our metrics map. 331*cdf0e10cSrcweir maGlyphMetricMap[nGlyphId] = std::make_pair(aBounding, advances); 332*cdf0e10cSrcweir } 333*cdf0e10cSrcweir #endif 334*cdf0e10cSrcweir } 335*cdf0e10cSrcweir 336*cdf0e10cSrcweir #endif 337