1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: pdfencoding.cpp
3 // Purpose:
4 // Author: Ulrich Telle
5 // Created: 2009-05-30
6 // Copyright: (c) Ulrich Telle
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 /// \file pdfencoding.cpp Implementation of encoding class
11
12 // For compilers that support precompilation, includes <wx.h>.
13 #include <wx/wxprec.h>
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include <wx/wx.h>
21 #endif
22
23 // includes
24 #include <wx/string.h>
25
26 #include "wx/pdfencoding.h"
27
28 #include "pdfglyphnames.inc"
29 #include "pdfcmapdata.inc"
30
31 bool
GlyphName2Unicode(const wxString & glyphName,wxUint32 & unicode)32 wxPdfEncoding::GlyphName2Unicode(const wxString& glyphName, wxUint32& unicode)
33 {
34 // TODO:
35 // 1. Drop all characters after period if any
36 // 2. Split into components using underscore as delimiter
37
38 // 3. map each component
39 // a. for ZapfDingBats use appropriate list
40 // b. search in AGL
41 // c. uniXXXXYYYYZZZZ map to XXXX, YYYY, ZZZZ resp.
42 // d. uXXXXXX map to XXXXXX
43 unicode = 0;
44 bool found = false;
45 int first = 0;
46 int last = (int) gs_glyphName2UnicodeTableSize - 1;
47 int mid;
48 while (!found && first < last)
49 {
50 mid = (first + last) / 2;
51 int relation = glyphName.Cmp(gs_glyphName2UnicodeTable[mid].glyphname);
52 if (relation == 0)
53 {
54 found = true;
55 unicode = gs_glyphName2UnicodeTable[mid].unicode;
56 }
57 else
58 {
59 if (relation < 0)
60 {
61 last = mid - 1;
62 }
63 else
64 {
65 first = mid + 1;
66 }
67 }
68 }
69 if (!found)
70 {
71 wxString glyphRest;
72 unsigned long convUni = 0;
73 if (glyphName.StartsWith(wxS("uni"), &glyphRest))
74 {
75 if (glyphRest.length() >= 4)
76 {
77 found = glyphRest.Mid(0,4).ToULong(&convUni, 16);
78 if (found) unicode = convUni;
79 }
80 }
81 else if (glyphName.StartsWith(wxS("u"), &glyphRest))
82 {
83 if (glyphRest.length() >= 6)
84 {
85 found = glyphRest.Mid(0,6).ToULong(&convUni, 16);
86 if (found) unicode = convUni;
87 }
88 }
89 }
90 return found;
91 }
92
93 bool
Unicode2GlyphName(wxUint32 unicode,wxString & glyphName)94 wxPdfEncoding::Unicode2GlyphName(wxUint32 unicode, wxString& glyphName)
95 {
96 glyphName = wxEmptyString;
97 bool found = false;
98 int first = 0;
99 int last = (int) gs_unicode2GlyphNameTableSize - 1;
100 int mid;
101 while (!found && first <= last)
102 {
103 mid = (first + last) / 2;
104 wxUint32 code = gs_unicode2GlyphNameTable[mid].unicode;
105 if (unicode == code)
106 {
107 found = true;
108 glyphName = gs_unicode2GlyphNameTable[mid].glyphname;
109 }
110 else
111 {
112 if (unicode < code)
113 {
114 last = mid - 1;
115 }
116 else
117 {
118 first = mid + 1;
119 }
120 }
121 }
122 return found;
123 }
124
125 wxArrayString
GetKnownEncodings()126 wxPdfEncoding::GetKnownEncodings()
127 {
128 wxArrayString knownEncodings;
129 size_t j = 0;
130 while (gs_encodingData[j].m_encodingName != NULL)
131 {
132 knownEncodings.Add(gs_encodingData[j].m_encodingName);
133 ++j;
134 }
135 return knownEncodings;
136 }
137
wxPdfEncoding()138 wxPdfEncoding::wxPdfEncoding()
139 {
140 m_encoding = wxEmptyString;
141 m_baseEncoding = wxEmptyString;
142 m_specific = false;
143 m_firstChar = 0;
144 m_lastChar = 0;
145 m_cmap.Alloc(256);
146 m_cmapBase.Alloc(256);
147 m_glyphNames.Alloc(256);
148 m_cmap.Insert(0, 0, 256);
149 m_cmapBase.Insert(0, 0, 256);
150 m_glyphNames.Insert(wxString(wxS(".notdef")), 0, 256);
151 m_encodingMap = NULL;
152 }
153
~wxPdfEncoding()154 wxPdfEncoding::~wxPdfEncoding()
155 {
156 if (m_encodingMap != NULL)
157 {
158 delete m_encodingMap;
159 }
160 }
161
wxPdfEncoding(const wxPdfEncoding & encoding)162 wxPdfEncoding::wxPdfEncoding(const wxPdfEncoding &encoding)
163 {
164 m_encoding = encoding.m_encoding;
165 m_baseEncoding = encoding.m_baseEncoding;
166 m_specific = encoding.m_specific;
167 m_firstChar = encoding.m_firstChar;
168 m_lastChar = encoding.m_lastChar;
169 m_cmap = encoding.m_cmap;
170 m_cmapBase = encoding.m_cmapBase;
171 m_glyphNames = encoding.m_glyphNames;
172 m_encodingMap = NULL;
173 }
174
175 wxPdfEncoding&
operator =(const wxPdfEncoding & encoding)176 wxPdfEncoding::operator=(const wxPdfEncoding& encoding)
177 {
178 m_encoding = encoding.m_encoding;
179 m_baseEncoding = encoding.m_baseEncoding;
180 m_specific = encoding.m_specific;
181 m_firstChar = encoding.m_firstChar;
182 m_lastChar = encoding.m_lastChar;
183 m_cmap = encoding.m_cmap;
184 m_cmapBase = encoding.m_cmapBase;
185 m_glyphNames = encoding.m_glyphNames;
186 m_encodingMap = NULL;
187 return *this;
188 }
189
190 bool
IsOk() const191 wxPdfEncoding::IsOk() const
192 {
193 return !m_encoding.IsEmpty();
194 }
195
196 bool
SetEncoding(const wxString & encoding)197 wxPdfEncoding::SetEncoding(const wxString& encoding)
198 {
199 wxString encodingName = encoding.Lower();
200 bool isWinAnsi = encodingName.IsSameAs(wxS("winansi"));
201 bool found = false;
202 size_t j = 0;
203 while (!found && gs_encodingData[j].m_encodingName != NULL)
204 {
205 if (encodingName.IsSameAs(gs_encodingData[j].m_encodingName))
206 {
207 found = true;
208 }
209 else
210 {
211 ++j;
212 }
213 }
214 if (found)
215 {
216 bool hasFullSize = gs_encodingData[j].m_fullsize;
217 m_encoding = encodingName;
218 m_baseEncoding = gs_encodingData[j].m_baseEncoding;
219 m_specific = false;
220 m_firstChar = 32;
221 m_lastChar = 255;
222 wxUint32 unicodeChar;
223 wxString glyphName;
224 int k;
225 for (k = 0; k < 128; ++k)
226 {
227 if (hasFullSize)
228 {
229 unicodeChar = (wxUint32) gs_encodingData[j].m_encodingMap[k];
230 m_cmap[k] = unicodeChar;
231 m_cmapBase[k] = unicodeChar;
232 }
233 else
234 {
235 unicodeChar = (wxUint32) k;
236 m_cmap[k] = unicodeChar;
237 m_cmapBase[k] = unicodeChar;
238 }
239 if (k >= m_firstChar && k != 127 && Unicode2GlyphName(unicodeChar, glyphName))
240 {
241 m_glyphNames[k] = glyphName;
242 }
243 else
244 {
245 if (k > 40 && isWinAnsi)
246 {
247 m_glyphNames[k] = wxString(wxS("bullet"));
248 }
249 else
250 {
251 m_glyphNames[k] = wxString(wxS(".notdef"));
252 }
253 }
254 }
255 for (k = 128; k < 256; ++k)
256 {
257 int delta = (hasFullSize) ? 0 : 128;
258 unicodeChar = (wxUint32) gs_encodingData[j].m_encodingMap[k-delta];
259 m_cmap[k] = unicodeChar;
260 m_cmapBase[k] = (wxUint32) gs_encodingData[j].m_encodingBase[k-delta];
261 if (Unicode2GlyphName(unicodeChar, glyphName))
262 {
263 m_glyphNames[k] = glyphName;
264 }
265 else
266 {
267 if (isWinAnsi)
268 {
269 m_glyphNames[k] = wxString(wxS("bullet"));
270 }
271 else
272 {
273 m_glyphNames[k] = wxString(wxS(".notdef"));
274 }
275 }
276 }
277 }
278 return found;
279 }
280
281 wxString
GetEncodingName() const282 wxPdfEncoding::GetEncodingName() const
283 {
284 return m_encoding;
285 }
286
287 wxString
GetBaseEncodingName() const288 wxPdfEncoding::GetBaseEncodingName() const
289 {
290 return m_baseEncoding;
291 }
292
293 wxString
GetDifferences() const294 wxPdfEncoding::GetDifferences() const
295 {
296 wxString diffs = wxEmptyString;
297 int last = 0;
298 int i;
299 for (i = m_firstChar; i <= m_lastChar; i++)
300 {
301 if (m_cmap[i] != 0x0000 && m_cmap[i] != m_cmapBase[i])
302 {
303 if (i != last+1)
304 {
305 diffs += wxString::Format(wxS("%d "), i);
306 }
307 last = i;
308 diffs = diffs + wxString(wxS("/")) + m_glyphNames[i] + wxString(wxS(" "));
309 }
310 }
311 return diffs;
312 }
313
314 wxPdfArrayUint32
GetCMap() const315 wxPdfEncoding::GetCMap() const
316 {
317 return m_cmap;
318 }
319
320 void
InitializeEncodingMap()321 wxPdfEncoding::InitializeEncodingMap()
322 {
323 if (m_encodingMap == NULL)
324 {
325 CreateEncodingConvMap();
326 }
327 }
328
329 const wxPdfChar2GlyphMap*
GetEncodingMap() const330 wxPdfEncoding::GetEncodingMap() const
331 {
332 return m_encodingMap;
333 }
334
335 wxArrayString
GetGlyphNames() const336 wxPdfEncoding::GetGlyphNames() const
337 {
338 return m_glyphNames;
339 }
340
341 void
CreateEncodingConvMap()342 wxPdfEncoding::CreateEncodingConvMap()
343 {
344 if (m_encodingMap == NULL)
345 {
346 m_encodingMap = new wxPdfChar2GlyphMap();
347 size_t n = m_cmap.GetCount();
348 size_t j;
349 for (j = 0; j < n; ++j)
350 {
351 (*m_encodingMap)[m_cmap[j]] = j;
352 }
353 }
354 }
355
356 // --- Encoding Checker
357
wxPdfEncodingChecker()358 wxPdfEncodingChecker::wxPdfEncodingChecker()
359 {
360 m_encoding = wxEmptyString;
361 }
362
~wxPdfEncodingChecker()363 wxPdfEncodingChecker::~wxPdfEncodingChecker()
364 {
365 }
366
367 wxString
GetEncodingName() const368 wxPdfEncodingChecker::GetEncodingName() const
369 {
370 return m_encoding;
371 }
372