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