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