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