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