LibreOffice Module vcl (master) 1
fontcharmap.cxx
Go to the documentation of this file.
1/*
2 * This file is part of the LibreOffice project.
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * This file incorporates work covered by the following license notice:
9 *
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
17 */
18#include <utility>
19#include <vcl/fontcharmap.hxx>
20#include <impfontcharmap.hxx>
21#include <sal/log.hxx>
22
23#include <algorithm>
24#include <vector>
25
27const std::vector<sal_uInt32> aDefaultUnicodeRanges = { 0x0020, 0xD800, 0xE000, 0xFFF0 };
28const std::vector<sal_uInt32> aDefaultSymbolRanges = { 0x0020, 0x0100, 0xF020, 0xF100 };
29
31{
32}
33
34ImplFontCharMap::ImplFontCharMap(bool bMicrosoftSymbolMap, std::vector<sal_uInt32> aRangeCodes)
35: maRangeCodes(std::move(aRangeCodes))
36, mnCharCount( 0 )
37, m_bMicrosoftSymbolMap(bMicrosoftSymbolMap)
38{
39 for (size_t i = 0; i < maRangeCodes.size(); i += 2)
40 {
41 sal_UCS4 cFirst = maRangeCodes[i];
42 sal_UCS4 cLast = maRangeCodes[i + 1];
43 mnCharCount += cLast - cFirst;
44 }
45}
46
47ImplFontCharMapRef const & ImplFontCharMap::getDefaultMap(bool bMicrosoftSymbolMap)
48{
49 const auto& rRanges = bMicrosoftSymbolMap ? aDefaultSymbolRanges : aDefaultUnicodeRanges;
50 g_pDefaultImplFontCharMap = ImplFontCharMapRef(new ImplFontCharMap(bMicrosoftSymbolMap, rRanges));
52}
53
55{
56 const bool bIsDefault = (maRangeCodes == aDefaultUnicodeRanges) || (maRangeCodes == aDefaultSymbolRanges);
57 return bIsDefault;
58}
59
60static unsigned GetUShort(const unsigned char* p) { return((p[0]<<8) | p[1]);}
61
62bool HasMicrosoftSymbolCmap(const unsigned char* pCmap, int nLength)
63{
64 // parse the table header and check for validity
65 if( !pCmap || (nLength < 24) )
66 return false;
67
68 if( GetUShort( pCmap ) != 0x0000 ) // simple check for CMAP corruption
69 return false;
70
71 int nSubTables = GetUShort(pCmap + 2);
72 if( (nSubTables <= 0) || (nSubTables > (nLength - 24) / 8) )
73 return false;
74
75 for (const unsigned char* p = pCmap + 4; --nSubTables >= 0; p += 8)
76 {
77 int nPlatform = GetUShort(p);
78 int nEncoding = GetUShort(p + 2);
79 // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html
80 // When the platformID is 3 (Windows), an encoding of 0 is Symbol
81 if (nPlatform == 3 && nEncoding == 0)
82 return true;
83 }
84
85 return false;
86}
87
89 : mpImplFontCharMap( ImplFontCharMap::getDefaultMap() )
90{
91}
92
94 : mpImplFontCharMap(std::move( pIFCMap ))
95{
96}
97
98FontCharMap::FontCharMap(bool bMicrosoftSymbolMap, std::vector<sal_uInt32> aRangeCodes)
99 : mpImplFontCharMap(new ImplFontCharMap(bMicrosoftSymbolMap, std::move(aRangeCodes)))
100{
101}
102
104{
105 mpImplFontCharMap = nullptr;
106}
107
109{
110 FontCharMapRef xFontCharMap( new FontCharMap( ImplFontCharMap::getDefaultMap(bMicrosoftSymbolMap) ) );
111 return xFontCharMap;
112}
113
115{
116 return mpImplFontCharMap->isDefaultMap();
117}
118
119bool FontCharMap::isMicrosoftSymbolMap() const { return mpImplFontCharMap->m_bMicrosoftSymbolMap; }
120
122{
123 return mpImplFontCharMap->mnCharCount;
124}
125
127{
128 const auto& rRanges = mpImplFontCharMap->maRangeCodes;
129 int nCount = 0;
130
131 // find and adjust range and char count for cMin
132 int nRangeMin = findRangeIndex( cMin );
133 if( nRangeMin & 1 )
134 ++nRangeMin;
135 else if (cMin > rRanges[nRangeMin])
136 nCount -= cMin - rRanges[nRangeMin];
137
138 // find and adjust range and char count for cMax
139 int nRangeMax = findRangeIndex( cMax );
140 if( nRangeMax & 1 )
141 --nRangeMax;
142 else
143 nCount -= rRanges[nRangeMax + 1] - cMax - 1;
144
145 // count chars in complete ranges between cMin and cMax
146 for( int i = nRangeMin; i <= nRangeMax; i+=2 )
147 nCount += rRanges[i + 1] - rRanges[i];
148
149 return nCount;
150}
151
153{
154 const int nRange = findRangeIndex( cChar );
155 if (nRange==0 && cChar < mpImplFontCharMap->maRangeCodes[0])
156 return false;
157 return ((nRange & 1) == 0); // inside a range
158}
159
161{
162 return mpImplFontCharMap->maRangeCodes.front();
163}
164
166{
167 return mpImplFontCharMap->maRangeCodes.back() - 1;
168}
169
171{
172 if( cChar < GetFirstChar() )
173 return GetFirstChar();
174 if( cChar >= GetLastChar() )
175 return GetLastChar();
176
177 int nRange = findRangeIndex( cChar + 1 );
178 if( nRange & 1 ) // outside of range?
179 return mpImplFontCharMap->maRangeCodes[nRange + 1]; // => first in next range
180 return (cChar + 1);
181}
182
184{
185 if( cChar <= GetFirstChar() )
186 return GetFirstChar();
187 if( cChar > GetLastChar() )
188 return GetLastChar();
189
190 int nRange = findRangeIndex( cChar - 1 );
191 if( nRange & 1 ) // outside a range?
192 return mpImplFontCharMap->maRangeCodes[nRange] - 1; // => last in prev range
193 return (cChar - 1);
194}
195
197{
198 // TODO: improve linear walk?
199 int nCharIndex = 0;
200 const auto& rRanges = mpImplFontCharMap->maRangeCodes;
201 for (size_t i = 0; i < rRanges.size(); i += 2)
202 {
203 sal_UCS4 cFirst = rRanges[i];
204 sal_UCS4 cLast = rRanges[i + 1];
205 if( cChar >= cLast )
206 nCharIndex += cLast - cFirst;
207 else if( cChar >= cFirst )
208 return nCharIndex + (cChar - cFirst);
209 else
210 break;
211 }
212
213 return -1;
214}
215
217{
218 // TODO: improve linear walk?
219 const auto& rRanges = mpImplFontCharMap->maRangeCodes;
220 for (size_t i = 0; i < rRanges.size(); i += 2)
221 {
222 sal_UCS4 cFirst = rRanges[i];
223 sal_UCS4 cLast = rRanges[i + 1];
224 nIndex -= cLast - cFirst;
225 if( nIndex < 0 )
226 return (cLast + nIndex);
227 }
228
229 // we can only get here with an out-of-bounds charindex
230 return mpImplFontCharMap->maRangeCodes.front();
231}
232
234{
235 const auto& rRanges = mpImplFontCharMap->maRangeCodes;
236 int nLower = 0;
237 int nMid = rRanges.size() / 2;
238 int nUpper = rRanges.size() - 1;
239 while( nLower < nUpper )
240 {
241 if (cChar >= rRanges[nMid])
242 nLower = nMid;
243 else
244 nUpper = nMid - 1;
245 nMid = (nLower + nUpper + 1) / 2;
246 }
247
248 return nMid;
249}
250
251/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_UCS4 GetFirstChar() const
Get the first character in the font character map.
sal_UCS4 GetCharFromIndex(int nCharIndex) const
Get the character at a particular index in the font character map.
FontCharMap()
A new FontCharMap is created based on a "default" map, which includes all codepoints in the Unicode B...
Definition: fontcharmap.cxx:88
ImplFontCharMapRef mpImplFontCharMap
bool HasChar(sal_UCS4) const
Does the font character map include the UCS4 character?
int GetIndexFromChar(sal_UCS4 cChar) const
Get the index of a particular character in the font character map.
int CountCharsInRange(sal_UCS4 cMin, sal_UCS4 cMax) const
Returns the number of chars supported by the font, which are inside the unicode range from cMin to cM...
sal_UCS4 GetPrevChar(sal_UCS4 cChar) const
Get the previous character in the font character map.
int findRangeIndex(sal_UCS4) const
sal_UCS4 GetLastChar() const
Get the last character in the font character map.
static FontCharMapRef GetDefaultMap(bool bMicrosoftSymbolMap)
Get the default font character map.
virtual ~FontCharMap() override
bool IsDefaultMap() const
Determines if the font character map is the "default".
sal_UCS4 GetNextChar(sal_UCS4 cChar) const
Get the next character in the font character map.
bool isMicrosoftSymbolMap() const
int GetCharCount() const
Get the number of characters in the font character map.
virtual ~ImplFontCharMap() override
Definition: fontcharmap.cxx:30
std::vector< sal_uInt32 > maRangeCodes
ImplFontCharMap(bool bMicrosoftSymbolMap, std::vector< sal_uInt32 > aRangeCodes)
Definition: fontcharmap.cxx:34
bool isDefaultMap() const
Definition: fontcharmap.cxx:54
static ImplFontCharMapRef const & getDefaultMap(bool bMicrosoftSymbolMap=false)
Definition: fontcharmap.cxx:47
int nCount
const std::vector< sal_uInt32 > aDefaultUnicodeRanges
Definition: fontcharmap.cxx:27
static ImplFontCharMapRef g_pDefaultImplFontCharMap
Definition: fontcharmap.cxx:26
const std::vector< sal_uInt32 > aDefaultSymbolRanges
Definition: fontcharmap.cxx:28
bool HasMicrosoftSymbolCmap(const unsigned char *pCmap, int nLength)
Definition: fontcharmap.cxx:62
static unsigned GetUShort(const unsigned char *p)
Definition: fontcharmap.cxx:60
tools::SvRef< ImplFontCharMap > ImplFontCharMapRef
sal_Int32 nIndex
void * p
int i
sal_uInt32 sal_UCS4
Definition: vclenum.hxx:160
sal_Int32 nLength