xref: /AOO41X/main/vcl/source/glyphs/graphite_adaptors.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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