merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / glyphs / graphite_adaptors.cxx
blob9b16318fdc40369ca58ccb4acbb8349d5f8d0d3f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: $
10 * $Revision: $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // Description: Implements the Graphite interfaces with access to the
32 // platform's font and graphics systems.
34 // MARKER(update_precomp.py): autogen include statement, do not remove
35 #include "precompiled_vcl.hxx"
37 // We need this to enable namespace support in libgrengine headers.
38 #define GR_NAMESPACE
40 // Header files
42 // Standard Library
43 #include <string>
44 #include <cassert>
45 // Libraries
46 #include <rtl/string.hxx>
47 #include <rtl/ustring.hxx>
48 #include <i18npool/mslangid.hxx>
49 // Platform
50 #ifndef WNT
51 #include <saldisp.hxx>
53 #include <vcl/salgdi.hxx>
55 #include <freetype/ftsynth.h>
57 // Module
58 #include "gcach_ftyp.hxx"
60 #include <vcl/graphite_features.hxx>
61 #include <vcl/graphite_adaptors.hxx>
63 // Module private type definitions and forward declarations.
65 using gr::GrResult;
66 namespace
68 inline float from_hinted(const int x) {
69 return static_cast<float>(x + 32) / 64.0;
71 typedef std::hash_map<long,bool> SilfMap;
72 SilfMap sSilfMap;
75 // class CharacterRenderProperties implentation.
77 FontProperties::FontProperties(const FreetypeServerFont &font) throw()
79 clrFore = gr::kclrBlack;
80 clrBack = gr::kclrTransparent;
82 pixHeight = from_hinted(font.GetMetricsFT().height);
84 switch (font.GetFontSelData().meWeight)
86 case WEIGHT_SEMIBOLD: case WEIGHT_BOLD:
87 case WEIGHT_ULTRABOLD: case WEIGHT_BLACK:
88 fBold = true;
89 break;
90 default :
91 fBold = false;
94 switch (font.GetFontSelData().meItalic)
96 case ITALIC_NORMAL: case ITALIC_OBLIQUE:
97 fItalic = true;
98 break;
99 default :
100 fItalic = false;
103 // Get the font name.
104 const sal_Unicode * name = font.GetFontSelData().maName.GetBuffer();
105 const size_t name_sz = std::min(sizeof szFaceName/sizeof(wchar_t)-1,
106 size_t(font.GetFontSelData().maName.Len()));
108 std::copy(name, name + name_sz, szFaceName);
109 szFaceName[name_sz] = '\0';
112 // class GraphiteFontAdaptor implementaion.
114 GraphiteFontAdaptor::GraphiteFontAdaptor(ServerFont & sfont, const sal_Int32 dpiX, const sal_Int32 dpiY)
115 : mrFont(static_cast<FreetypeServerFont &>(sfont)),
116 maFontProperties(static_cast<FreetypeServerFont &>(sfont)),
117 mnDpiX(dpiX),
118 mnDpiY(dpiY),
119 mfAscent(from_hinted(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().ascender)),
120 mfDescent(from_hinted(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().descender)),
121 mfEmUnits(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().y_ppem),
122 mpFeatures(NULL)
124 //std::wstring face_name(maFontProperties.szFaceName);
125 const rtl::OString aLang = MsLangId::convertLanguageToIsoByteString( sfont.GetFontSelData().meLanguage );
126 #ifdef DEBUG
127 printf("GraphiteFontAdaptor %lx\n", (long)this);
128 #endif
129 rtl::OString name = rtl::OUStringToOString(
130 sfont.GetFontSelData().maTargetName, RTL_TEXTENCODING_UTF8 );
131 sal_Int32 nFeat = name.indexOf(grutils::GrFeatureParser::FEAT_PREFIX) + 1;
132 if (nFeat > 0)
134 rtl::OString aFeat = name.copy(nFeat, name.getLength() - nFeat);
135 mpFeatures = new grutils::GrFeatureParser(*this, aFeat.getStr(), aLang.getStr());
136 #ifdef DEBUG
137 printf("GraphiteFontAdaptor %s/%s/%s %x language %d features %d errors\n",
138 rtl::OUStringToOString( sfont.GetFontSelData().maName,
139 RTL_TEXTENCODING_UTF8 ).getStr(),
140 rtl::OUStringToOString( sfont.GetFontSelData().maTargetName,
141 RTL_TEXTENCODING_UTF8 ).getStr(),
142 rtl::OUStringToOString( sfont.GetFontSelData().maSearchName,
143 RTL_TEXTENCODING_UTF8 ).getStr(),
144 sfont.GetFontSelData().meLanguage,
145 (int)mpFeatures->getFontFeatures(NULL), mpFeatures->parseErrors());
146 #endif
148 else
150 mpFeatures = new grutils::GrFeatureParser(*this, aLang.getStr());
154 GraphiteFontAdaptor::GraphiteFontAdaptor(const GraphiteFontAdaptor &rhs) throw()
155 : Font(rhs),
156 mrFont (rhs.mrFont), maFontProperties(rhs.maFontProperties),
157 mnDpiX(rhs.mnDpiX), mnDpiY(rhs.mnDpiY),
158 mfAscent(rhs.mfAscent), mfDescent(rhs.mfDescent), mfEmUnits(rhs.mfEmUnits),
159 mpFeatures(NULL)
161 if (rhs.mpFeatures) mpFeatures = new grutils::GrFeatureParser(*(rhs.mpFeatures));
165 GraphiteFontAdaptor::~GraphiteFontAdaptor() throw()
167 maGlyphMetricMap.clear();
168 if (mpFeatures) delete mpFeatures;
169 mpFeatures = NULL;
172 void GraphiteFontAdaptor::UniqueCacheInfo(std::wstring & face_name_out, bool & bold_out, bool & italic_out)
174 face_name_out = maFontProperties.szFaceName;
175 bold_out = maFontProperties.fBold;
176 italic_out = maFontProperties.fItalic;
179 bool GraphiteFontAdaptor::IsGraphiteEnabledFont(ServerFont & font) throw()
181 // NOTE: this assumes that the same FTFace pointer won't be reused,
182 // so FtFontInfo::ReleaseFaceFT must only be called at shutdown.
183 FreetypeServerFont & aFtFont = dynamic_cast<FreetypeServerFont &>(font);
184 FT_Face aFace = reinterpret_cast<FT_FaceRec_*>(aFtFont.GetFtFace());
185 SilfMap::iterator i = sSilfMap.find(reinterpret_cast<long>(aFace));
186 if (i != sSilfMap.end())
188 #ifdef DEBUG
189 if (static_cast<bool>(aFtFont.GetTable("Silf", 0)) != (*i).second)
190 printf("Silf cache font mismatch\n");
191 #endif
192 return (*i).second;
194 bool bHasSilf = aFtFont.GetTable("Silf", 0);
195 sSilfMap[reinterpret_cast<long>(aFace)] = bHasSilf;
196 return bHasSilf;
200 gr::Font * GraphiteFontAdaptor::copyThis() {
201 return new GraphiteFontAdaptor(*this);
205 unsigned int GraphiteFontAdaptor::getDPIx() {
206 return mnDpiX;
210 unsigned int GraphiteFontAdaptor::getDPIy() {
211 return mnDpiY;
215 float GraphiteFontAdaptor::ascent() {
216 return mfAscent;
220 float GraphiteFontAdaptor::descent() {
221 return mfDescent;
225 bool GraphiteFontAdaptor::bold() {
226 return maFontProperties.fBold;
230 bool GraphiteFontAdaptor::italic() {
231 return maFontProperties.fItalic;
235 float GraphiteFontAdaptor::height() {
236 return maFontProperties.pixHeight;
240 void GraphiteFontAdaptor::getFontMetrics(float * ascent_out, float * descent_out, float * em_square_out) {
241 if (ascent_out) *ascent_out = mfAscent;
242 if (descent_out) *descent_out = mfDescent;
243 if (em_square_out) *em_square_out = mfEmUnits;
247 const void * GraphiteFontAdaptor::getTable(gr::fontTableId32 table_id, size_t * buffer_sz)
249 char tag_name[5] = {char(table_id >> 24), char(table_id >> 16), char(table_id >> 8), char(table_id), 0};
250 ULONG temp = *buffer_sz;
252 const void * const tbl_buf = static_cast<FreetypeServerFont &>(mrFont).GetTable(tag_name, &temp);
253 *buffer_sz = temp;
255 return tbl_buf;
258 #define fix26_6(x) (x >> 6) + (x & 32 ? (x > 0 ? 1 : 0) : (x < 0 ? -1 : 0))
260 // Return the glyph's metrics in pixels.
261 void GraphiteFontAdaptor::getGlyphMetrics(gr::gid16 nGlyphId, gr::Rect & aBounding, gr::Point & advances)
263 // Graphite gets really confused if the glyphs have been transformed, so
264 // if orientation has been set we can't use the font's glyph cache
265 // unfortunately the font selection data, doesn't always have the orientation
266 // set, even if it was when the glyphs were cached, so we use our own cache.
268 // const GlyphMetric & metric = mrFont.GetGlyphMetric(nGlyphId);
270 // aBounding.right = aBounding.left = metric.GetOffset().X();
271 // aBounding.bottom = aBounding.top = -metric.GetOffset().Y();
272 // aBounding.right += metric.GetSize().Width();
273 // aBounding.bottom -= metric.GetSize().Height();
275 // advances.x = metric.GetDelta().X();
276 // advances.y = -metric.GetDelta().Y();
278 GlyphMetricMap::const_iterator gm_itr = maGlyphMetricMap.find(nGlyphId);
279 if (gm_itr != maGlyphMetricMap.end())
281 // We've cached the results from last time.
282 aBounding = gm_itr->second.first;
283 advances = gm_itr->second.second;
285 else
287 // We need to look up the glyph.
288 FT_Int nLoadFlags = mrFont.GetLoadFlags();
290 FT_Face aFace = reinterpret_cast<FT_Face>(mrFont.GetFtFace());
291 if (!aFace)
293 aBounding.top = aBounding.bottom = aBounding.left = aBounding.right = 0;
294 advances.x = advances.y = 0;
295 return;
297 FT_Error aStatus = -1;
298 aStatus = FT_Load_Glyph(aFace, nGlyphId, nLoadFlags);
299 if( aStatus != FT_Err_Ok || (!aFace->glyph))
301 aBounding.top = aBounding.bottom = aBounding.left = aBounding.right = 0;
302 advances.x = advances.y = 0;
303 return;
305 // check whether we need synthetic bold/italic otherwise metric is wrong
306 if (mrFont.NeedsArtificialBold())
307 FT_GlyphSlot_Embolden(aFace->glyph);
309 if (mrFont.NeedsArtificialItalic())
310 FT_GlyphSlot_Oblique(aFace->glyph);
312 const FT_Glyph_Metrics &gm = aFace->glyph->metrics;
314 // Fill out the bounding box an advances.
315 aBounding.top = aBounding.bottom = fix26_6(gm.horiBearingY);
316 aBounding.bottom -= fix26_6(gm.height);
317 aBounding.left = aBounding.right = fix26_6(gm.horiBearingX);
318 aBounding.right += fix26_6(gm.width);
319 advances.x = fix26_6(gm.horiAdvance);
320 advances.y = 0;
322 // Now add an entry to our metrics map.
323 maGlyphMetricMap[nGlyphId] = std::make_pair(aBounding, advances);
327 #endif