1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <string.h>
32 
33 #include "psputil.hxx"
34 
35 #include "tools/debug.hxx"
36 
37 namespace psp {
38 
39 /*
40  * string convenience routines
41  */
42 
43 sal_Int32
44 getHexValueOf (sal_Int32 nValue, sal_Char* pBuffer)
45 {
46     const static sal_Char pHex [0x10] = {
47         '0', '1', '2', '3', '4', '5', '6', '7',
48         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
49 
50     pBuffer[0] = pHex [(nValue & 0xF0) >> 4];
51     pBuffer[1] = pHex [(nValue & 0x0F)     ];
52 
53     return 2;
54 }
55 
56 sal_Int32
57 getAlignedHexValueOf (sal_Int32 nValue, sal_Char* pBuffer)
58 {
59     // get sign
60     sal_Bool bNegative = nValue < 0;
61     nValue = bNegative ? -nValue : nValue;
62 
63     // get required buffer size, must be a multiple of two
64     sal_Int32 nPrecision;
65     if (nValue < 0x80)
66         nPrecision = 2;
67     else
68         if (nValue < 0x8000)
69             nPrecision = 4;
70         else
71             if (nValue < 0x800000)
72                 nPrecision = 6;
73             else
74                 nPrecision = 8;
75 
76     // convert the int into its hex representation, write it into the buffer
77     sal_Int32 nRet = nPrecision;
78     while (nPrecision)
79     {
80         nPrecision -= getHexValueOf (nValue % 256, pBuffer + nPrecision - 2 );
81         nValue /= 256;
82     }
83 
84     // set sign bit
85     if (bNegative)
86     {
87         switch (pBuffer[0])
88         {
89             case '0' : pBuffer[0] = '8'; break;
90             case '1' : pBuffer[0] = '9'; break;
91             case '2' : pBuffer[0] = 'A'; break;
92             case '3' : pBuffer[0] = 'B'; break;
93             case '4' : pBuffer[0] = 'C'; break;
94             case '5' : pBuffer[0] = 'D'; break;
95             case '6' : pBuffer[0] = 'E'; break;
96             case '7' : pBuffer[0] = 'F'; break;
97             default: DBG_ERROR("Already a signed value");
98         }
99     }
100 
101     // report precision
102     return nRet;
103 }
104 
105 
106 sal_Int32
107 getValueOf (sal_Int32 nValue, sal_Char* pBuffer)
108 {
109     sal_Int32 nChar = 0;
110     if (nValue < 0)
111     {
112         pBuffer [nChar++] = '-';
113         nValue *= -1;
114     }
115     else
116         if (nValue == 0)
117         {
118             pBuffer [nChar++] = '0';
119             return nChar;
120         }
121 
122     sal_Char  pInvBuffer [32];
123     sal_Int32 nInvChar = 0;
124     while (nValue > 0)
125     {
126         pInvBuffer [nInvChar++] = '0' + nValue % 10;
127         nValue /= 10;
128     }
129     while (nInvChar > 0)
130     {
131         pBuffer [nChar++] = pInvBuffer [--nInvChar];
132     }
133 
134     return nChar;
135 }
136 
137 sal_Int32
138 appendStr (const sal_Char* pSrc, sal_Char* pDst)
139 {
140     sal_Int32 nBytes = strlen (pSrc);
141     strncpy (pDst, pSrc, nBytes + 1);
142 
143     return nBytes;
144 }
145 
146 sal_Int32
147 appendStr (const sal_Char* pSrc, sal_Char* pDst, sal_Int32 nBytes)
148 {
149     strncpy (pDst, pSrc, nBytes);
150     pDst [nBytes] = '\0';
151     return nBytes;
152 }
153 
154 /*
155  * copy strings to file
156  */
157 
158 sal_Bool
159 WritePS (osl::File* pFile, const sal_Char* pString)
160 {
161     sal_uInt64 nInLength = rtl_str_getLength (pString);
162     sal_uInt64 nOutLength = 0;
163 
164     if (nInLength > 0 && pFile)
165         pFile->write (pString, nInLength, nOutLength);
166 
167     return nInLength == nOutLength;
168 }
169 
170 sal_Bool
171 WritePS (osl::File* pFile, const sal_Char* pString, sal_uInt64 nInLength)
172 {
173     sal_uInt64 nOutLength = 0;
174 
175     if (nInLength > 0 && pFile)
176         pFile->write (pString, nInLength, nOutLength);
177 
178     return nInLength == nOutLength;
179 }
180 
181 sal_Bool
182 WritePS (osl::File* pFile, const rtl::OString &rString)
183 {
184     sal_uInt64 nInLength = rString.getLength();
185     sal_uInt64 nOutLength = 0;
186 
187     if (nInLength > 0 && pFile)
188         pFile->write (rString, nInLength, nOutLength);
189 
190     return nInLength == nOutLength;
191 }
192 
193 sal_Bool
194 WritePS (osl::File* pFile, const rtl::OUString &rString)
195 {
196     return WritePS (pFile, rtl::OUStringToOString(rString, RTL_TEXTENCODING_ASCII_US));
197 }
198 
199 /*
200  * cache converter for use in postscript drawing routines
201  */
202 
203 ConverterFactory::ConverterFactory()
204 {
205 }
206 
207 ConverterFactory::~ConverterFactory ()
208 {
209     for( std::map< rtl_TextEncoding, rtl_UnicodeToTextConverter >::const_iterator it = m_aConverters.begin(); it != m_aConverters.end(); ++it )
210             rtl_destroyUnicodeToTextConverter (it->second);
211 }
212 
213 rtl_UnicodeToTextConverter
214 ConverterFactory::Get (rtl_TextEncoding nEncoding)
215 {
216     if (rtl_isOctetTextEncoding( nEncoding ))
217     {
218         std::map< rtl_TextEncoding, rtl_UnicodeToTextConverter >::const_iterator it =
219             m_aConverters.find( nEncoding );
220         rtl_UnicodeToTextConverter aConverter;
221         if (it == m_aConverters.end())
222         {
223             aConverter = rtl_createUnicodeToTextConverter (nEncoding);
224             m_aConverters[nEncoding] = aConverter;
225         }
226         else
227             aConverter = it->second;
228         return aConverter;
229     }
230     return NULL;
231 }
232 
233 // wrapper for rtl_convertUnicodeToText that handles the usual cases for
234 // textconversion in drawtext
235 sal_Size
236 ConverterFactory::Convert (const sal_Unicode *pText, int nTextLen,
237                            sal_uChar *pBuffer, sal_Size nBufferSize, rtl_TextEncoding nEncoding)
238 {
239     const sal_uInt32 nCvtFlags =  RTL_UNICODETOTEXT_FLAGS_UNDEFINED_QUESTIONMARK
240         | RTL_UNICODETOTEXT_FLAGS_INVALID_QUESTIONMARK ;
241     sal_uInt32  nCvtInfo;
242     sal_Size    nCvtChars;
243 
244     rtl_UnicodeToTextConverter aConverter = Get (nEncoding);
245     rtl_UnicodeToTextContext   aContext   = rtl_createUnicodeToTextContext (aConverter);
246 
247     sal_Size nSize = rtl_convertUnicodeToText (aConverter, aContext,
248                                                pText, nTextLen, (sal_Char*)pBuffer, nBufferSize,
249                                                nCvtFlags, &nCvtInfo, &nCvtChars);
250 
251     rtl_destroyUnicodeToTextContext (aConverter, aContext);
252 
253     return nSize;
254 }
255 
256 ConverterFactory*
257 GetConverterFactory ()
258 {
259     static ConverterFactory* pCvt = NULL;
260 
261     if (pCvt == NULL)
262         pCvt = new ConverterFactory;
263 
264     return pCvt;
265 }
266 
267 
268 } /* namespace psp */
269