/src/libreoffice/vcl/source/gdi/salmisc.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <vcl/BitmapReadAccess.hxx> |
21 | | #include <vcl/salgtype.hxx> |
22 | | #include <bitmap/bmpfast.hxx> |
23 | | #include <o3tl/safeint.hxx> |
24 | | #include <osl/diagnose.h> |
25 | | #include <sal/log.hxx> |
26 | | #include <tools/helpers.hxx> |
27 | | #include <memory> |
28 | | |
29 | 6.75k | #define IMPL_CASE_SET_FORMAT( Format, BitCount ) \ |
30 | 6.75k | case( ScanlineFormat::Format ): \ |
31 | 6.75k | { \ |
32 | 6.75k | pFncSetPixel = BitmapReadAccess::SetPixelFor##Format; \ |
33 | 6.75k | pDstBuffer->mnBitCount = BitCount; \ |
34 | 6.75k | } \ |
35 | 6.75k | break |
36 | | |
37 | 54.0k | #define DOUBLE_SCANLINES() \ |
38 | 54.0k | while( ( nActY < nHeight1 ) && ( pMapY[ nActY + 1 ] == nMapY ) ) \ |
39 | 0 | { \ |
40 | 0 | memcpy( pDstScanMap[ nActY + 1 ], pDstScan, rDstBuffer.mnScanlineSize ); \ |
41 | 0 | nActY++; \ |
42 | 0 | } |
43 | | |
44 | | constexpr int TC_TO_PAL_COLORS = 4096; |
45 | | |
46 | | static tools::Long ImplIndexFromColor( const BitmapColor& rCol ) |
47 | 0 | { |
48 | 0 | return ( ( static_cast<tools::Long>(rCol.GetBlue()) >> 4) << 8 ) | |
49 | 0 | ( ( static_cast<tools::Long>(rCol.GetGreen()) >> 4 ) << 4 ) | |
50 | 0 | ( static_cast<tools::Long>(rCol.GetRed()) >> 4 ); |
51 | 0 | } |
52 | | |
53 | | static void ImplPALToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer, |
54 | | FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel, |
55 | | Scanline* pSrcScanMap, Scanline* pDstScanMap, sal_Int32 const * pMapX, const sal_Int32* pMapY ) |
56 | 0 | { |
57 | 0 | const tools::Long nHeight1 = rDstBuffer.mnHeight - 1; |
58 | 0 | BitmapPalette aColMap( rSrcBuffer.maPalette.GetEntryCount() ); |
59 | 0 | BitmapColor* pColMapBuf = aColMap.ImplGetColorBuffer(); |
60 | 0 | BitmapColor aIndex( 0 ); |
61 | |
|
62 | 0 | for( sal_uInt16 i = 0, nSrcCount = aColMap.GetEntryCount(), nDstCount = rDstBuffer.maPalette.GetEntryCount(); i < nSrcCount; i++ ) |
63 | 0 | { |
64 | 0 | if( ( i < nDstCount ) && ( rSrcBuffer.maPalette[ i ] == rDstBuffer.maPalette[ i ] ) ) |
65 | 0 | aIndex.SetIndex( sal::static_int_cast<sal_uInt8>(i) ); |
66 | 0 | else |
67 | 0 | aIndex.SetIndex( sal::static_int_cast<sal_uInt8>(rDstBuffer.maPalette.GetBestIndex( rSrcBuffer.maPalette[ i ] )) ); |
68 | |
|
69 | 0 | pColMapBuf[ i ] = aIndex; |
70 | 0 | } |
71 | |
|
72 | 0 | for (tools::Long nActY = 0; nActY < rDstBuffer.mnHeight; ++nActY) |
73 | 0 | { |
74 | 0 | tools::Long nMapY = pMapY[nActY]; |
75 | 0 | Scanline pSrcScan(pSrcScanMap[nMapY]), pDstScan(pDstScanMap[nActY]); |
76 | |
|
77 | 0 | for (tools::Long nX = 0; nX < rDstBuffer.mnWidth; ++nX) |
78 | 0 | pFncSetPixel( pDstScan, nX, pColMapBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ] ).GetIndex() ] ); |
79 | |
|
80 | 0 | DOUBLE_SCANLINES(); |
81 | 0 | } |
82 | 0 | } |
83 | | |
84 | | static void ImplPALToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer const & rDstBuffer, |
85 | | FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel, |
86 | | Scanline* pSrcScanMap, Scanline* pDstScanMap, sal_Int32 const * pMapX, const sal_Int32* pMapY ) |
87 | 6.75k | { |
88 | 6.75k | const tools::Long nHeight1 = rDstBuffer.mnHeight - 1; |
89 | 6.75k | const BitmapColor* pColBuf = rSrcBuffer.maPalette.ImplGetColorBuffer(); |
90 | | |
91 | 6.75k | if (rSrcBuffer.meFormat == ScanlineFormat::N8BitPal) |
92 | 6.75k | { |
93 | 60.7k | for (tools::Long nActY = 0; nActY < rDstBuffer.mnHeight; ++nActY) |
94 | 54.0k | { |
95 | 54.0k | tools::Long nMapY = pMapY[nActY]; |
96 | 54.0k | Scanline pSrcScan(pSrcScanMap[nMapY]), pDstScan(pDstScanMap[nActY]); |
97 | | |
98 | 486k | for (tools::Long nX = 0; nX < rDstBuffer.mnWidth; ++nX) |
99 | 432k | pFncSetPixel( pDstScan, nX, pColBuf[ pSrcScan[ pMapX[ nX ] ] ] ); |
100 | | |
101 | 54.0k | DOUBLE_SCANLINES(); |
102 | 54.0k | } |
103 | 6.75k | } |
104 | 0 | else |
105 | 0 | { |
106 | 0 | for (tools::Long nActY = 0; nActY < rDstBuffer.mnHeight; ++nActY) |
107 | 0 | { |
108 | 0 | tools::Long nMapY = pMapY[nActY]; |
109 | 0 | Scanline pSrcScan(pSrcScanMap[nMapY]), pDstScan(pDstScanMap[nActY]); |
110 | |
|
111 | 0 | for (tools::Long nX = 0; nX < rDstBuffer.mnWidth; ++nX) |
112 | 0 | pFncSetPixel( pDstScan, nX, pColBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ] ).GetIndex() ] ); |
113 | |
|
114 | 0 | DOUBLE_SCANLINES(); |
115 | 0 | } |
116 | 0 | } |
117 | 6.75k | } |
118 | | |
119 | | static void ImplTCToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer const & rDstBuffer, |
120 | | FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel, |
121 | | Scanline* pSrcScanMap, Scanline* pDstScanMap, sal_Int32 const * pMapX, const sal_Int32* pMapY ) |
122 | 0 | { |
123 | 0 | const tools::Long nHeight1 = rDstBuffer.mnHeight - 1; |
124 | |
|
125 | 0 | if (rSrcBuffer.meFormat == ScanlineFormat::N24BitTcBgr) |
126 | 0 | { |
127 | 0 | BitmapColor aCol; |
128 | 0 | sal_uInt8* pPixel = nullptr; |
129 | |
|
130 | 0 | for (tools::Long nActY = 0; nActY < rDstBuffer.mnHeight; ++nActY) |
131 | 0 | { |
132 | 0 | tools::Long nMapY = pMapY[nActY]; |
133 | 0 | Scanline pSrcScan(pSrcScanMap[nMapY]), pDstScan(pDstScanMap[nActY]); |
134 | |
|
135 | 0 | for (tools::Long nX = 0; nX < rDstBuffer.mnWidth; ++nX) |
136 | 0 | { |
137 | 0 | pPixel = pSrcScan + pMapX[ nX ] * 3; |
138 | 0 | aCol.SetBlue( *pPixel++ ); |
139 | 0 | aCol.SetGreen( *pPixel++ ); |
140 | 0 | aCol.SetRed( *pPixel ); |
141 | 0 | pFncSetPixel( pDstScan, nX, aCol ); |
142 | 0 | } |
143 | |
|
144 | 0 | DOUBLE_SCANLINES() |
145 | 0 | } |
146 | 0 | } |
147 | 0 | else |
148 | 0 | { |
149 | 0 | for (tools::Long nActY = 0; nActY < rDstBuffer.mnHeight; ++nActY) |
150 | 0 | { |
151 | 0 | tools::Long nMapY = pMapY[nActY]; |
152 | 0 | Scanline pSrcScan(pSrcScanMap[nMapY]), pDstScan(pDstScanMap[nActY]); |
153 | |
|
154 | 0 | for (tools::Long nX = 0; nX < rDstBuffer.mnWidth; ++nX) |
155 | 0 | pFncSetPixel( pDstScan, nX, pFncGetPixel( pSrcScan, pMapX[ nX ] ) ); |
156 | |
|
157 | 0 | DOUBLE_SCANLINES(); |
158 | 0 | } |
159 | 0 | } |
160 | 0 | } |
161 | | |
162 | | static void ImplTCToPAL( BitmapBuffer const & rDstBuffer, |
163 | | FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel, |
164 | | Scanline* pSrcScanMap, Scanline* pDstScanMap, sal_Int32 const * pMapX, const sal_Int32* pMapY ) |
165 | 0 | { |
166 | 0 | const tools::Long nHeight1 = rDstBuffer.mnHeight- 1; |
167 | 0 | std::unique_ptr<sal_uInt8[]> pColToPalMap(new sal_uInt8[ TC_TO_PAL_COLORS ]); |
168 | 0 | BitmapColor aIndex( 0 ); |
169 | |
|
170 | 0 | for( tools::Long nR = 0; nR < 16; nR++ ) |
171 | 0 | { |
172 | 0 | for( tools::Long nG = 0; nG < 16; nG++ ) |
173 | 0 | { |
174 | 0 | for( tools::Long nB = 0; nB < 16; nB++ ) |
175 | 0 | { |
176 | 0 | BitmapColor aCol( sal::static_int_cast<sal_uInt8>(nR << 4), |
177 | 0 | sal::static_int_cast<sal_uInt8>(nG << 4), |
178 | 0 | sal::static_int_cast<sal_uInt8>(nB << 4) ); |
179 | 0 | pColToPalMap[ ImplIndexFromColor( aCol ) ] = static_cast<sal_uInt8>(rDstBuffer.maPalette.GetBestIndex( aCol )); |
180 | 0 | } |
181 | 0 | } |
182 | 0 | } |
183 | |
|
184 | 0 | for (tools::Long nActY = 0; nActY < rDstBuffer.mnHeight; ++nActY) |
185 | 0 | { |
186 | 0 | tools::Long nMapY = pMapY[nActY]; |
187 | 0 | Scanline pSrcScan(pSrcScanMap[nMapY]), pDstScan(pDstScanMap[nActY]); |
188 | |
|
189 | 0 | for (tools::Long nX = 0; nX < rDstBuffer.mnWidth; ++nX) |
190 | 0 | { |
191 | 0 | aIndex.SetIndex( pColToPalMap[ ImplIndexFromColor( pFncGetPixel( pSrcScan, pMapX[ nX ] ) ) ] ); |
192 | 0 | pFncSetPixel( pDstScan, nX, aIndex ); |
193 | 0 | } |
194 | |
|
195 | 0 | DOUBLE_SCANLINES(); |
196 | 0 | } |
197 | 0 | } |
198 | | |
199 | | std::optional<BitmapBuffer> StretchAndConvert( |
200 | | const BitmapBuffer& rSrcBuffer, const SalTwoRect& rTwoRect, |
201 | | ScanlineFormat nDstBitmapFormat, std::optional<BitmapPalette> pDstPal ) |
202 | 6.75k | { |
203 | 6.75k | FncGetPixel pFncGetPixel; |
204 | 6.75k | FncSetPixel pFncSetPixel; |
205 | 6.75k | std::optional<BitmapBuffer> pDstBuffer(std::in_place); |
206 | | |
207 | | |
208 | 6.75k | pDstBuffer->meDirection = rSrcBuffer.meDirection; |
209 | | // set function for getting pixels |
210 | 6.75k | pFncGetPixel = BitmapReadAccess::GetPixelFunction(rSrcBuffer.meFormat); |
211 | 6.75k | if( !pFncGetPixel ) |
212 | 0 | { |
213 | | // should never come here |
214 | | // initialize pFncGetPixel to something valid that is |
215 | | // least likely to crash |
216 | 0 | pFncGetPixel = BitmapReadAccess::GetPixelForN8BitPal; |
217 | 0 | OSL_FAIL( "unknown read format" ); |
218 | 0 | } |
219 | | |
220 | | // set function for setting pixels |
221 | 6.75k | switch (nDstBitmapFormat) |
222 | 6.75k | { |
223 | 0 | IMPL_CASE_SET_FORMAT( N8BitPal, 8 ); |
224 | 0 | IMPL_CASE_SET_FORMAT( N24BitTcBgr, 24 ); |
225 | 0 | IMPL_CASE_SET_FORMAT( N24BitTcRgb, 24 ); |
226 | 0 | IMPL_CASE_SET_FORMAT( N32BitTcAbgr, 32 ); |
227 | 0 | IMPL_CASE_SET_FORMAT( N32BitTcXbgr, 32 ); |
228 | 0 | IMPL_CASE_SET_FORMAT( N32BitTcArgb, 32 ); |
229 | 0 | IMPL_CASE_SET_FORMAT( N32BitTcXrgb, 32 ); |
230 | 6.75k | IMPL_CASE_SET_FORMAT( N32BitTcBgra, 32 ); |
231 | 0 | IMPL_CASE_SET_FORMAT( N32BitTcBgrx, 32 ); |
232 | 0 | IMPL_CASE_SET_FORMAT( N32BitTcRgba, 32 ); |
233 | 0 | IMPL_CASE_SET_FORMAT( N32BitTcRgbx, 32 ); |
234 | | |
235 | 0 | default: |
236 | | // should never come here |
237 | | // initialize pFncSetPixel to something valid that is |
238 | | // least likely to crash |
239 | 0 | pFncSetPixel = BitmapReadAccess::SetPixelForN8BitPal; |
240 | 0 | pDstBuffer->mnBitCount = 8; |
241 | 0 | assert(false && "unknown write format" ); |
242 | 0 | break; |
243 | 6.75k | } |
244 | | |
245 | | // fill destination buffer |
246 | 6.75k | pDstBuffer->meFormat = nDstBitmapFormat; |
247 | 6.75k | pDstBuffer->mnWidth = rTwoRect.mnDestWidth; |
248 | 6.75k | pDstBuffer->mnHeight = rTwoRect.mnDestHeight; |
249 | 6.75k | tools::Long nScanlineBase; |
250 | 6.75k | bool bFail = o3tl::checked_multiply<tools::Long>(pDstBuffer->mnBitCount, pDstBuffer->mnWidth, nScanlineBase); |
251 | 6.75k | if (bFail) |
252 | 0 | { |
253 | 0 | SAL_WARN("vcl.gdi", "checked multiply failed"); |
254 | 0 | pDstBuffer->mpBits = nullptr; |
255 | 0 | return std::nullopt; |
256 | 0 | } |
257 | 6.75k | pDstBuffer->mnScanlineSize = AlignedWidth4Bytes(nScanlineBase); |
258 | 6.75k | if (pDstBuffer->mnScanlineSize < nScanlineBase/8) |
259 | 0 | { |
260 | 0 | SAL_WARN("vcl.gdi", "scanline calculation wraparound"); |
261 | 0 | pDstBuffer->mpBits = nullptr; |
262 | 0 | return std::nullopt; |
263 | 0 | } |
264 | 6.75k | try |
265 | 6.75k | { |
266 | 6.75k | pDstBuffer->mpBits = new sal_uInt8[ pDstBuffer->mnScanlineSize * pDstBuffer->mnHeight ]; |
267 | 6.75k | } |
268 | 6.75k | catch( const std::bad_alloc& ) |
269 | 6.75k | { |
270 | | // memory exception, clean up |
271 | 0 | pDstBuffer->mpBits = nullptr; |
272 | 0 | return std::nullopt; |
273 | 0 | } |
274 | | |
275 | | // do we need a destination palette or color mask? |
276 | 6.75k | if (nDstBitmapFormat == ScanlineFormat::N8BitPal) |
277 | 0 | { |
278 | 0 | assert(pDstPal && "destination buffer requires palette"); |
279 | 0 | if (!pDstPal) |
280 | 0 | { |
281 | 0 | return std::nullopt; |
282 | 0 | } |
283 | 0 | pDstBuffer->maPalette = *pDstPal; |
284 | 0 | } |
285 | | |
286 | | // short circuit the most important conversions |
287 | 6.75k | bool bFastConvert = ImplFastBitmapConversion( *pDstBuffer, rSrcBuffer, rTwoRect ); |
288 | 6.75k | if( bFastConvert ) |
289 | 0 | return pDstBuffer; |
290 | | |
291 | 6.75k | std::unique_ptr<Scanline[]> pSrcScan; |
292 | 6.75k | std::unique_ptr<Scanline[]> pDstScan; |
293 | 6.75k | std::unique_ptr<sal_Int32[]> pMapX; |
294 | 6.75k | std::unique_ptr<sal_Int32[]> pMapY; |
295 | | |
296 | 6.75k | try |
297 | 6.75k | { |
298 | 6.75k | pSrcScan.reset(new Scanline[rSrcBuffer.mnHeight]); |
299 | 6.75k | pDstScan.reset(new Scanline[pDstBuffer->mnHeight]); |
300 | 6.75k | pMapX.reset(new sal_Int32[pDstBuffer->mnWidth]); |
301 | 6.75k | pMapY.reset(new sal_Int32[pDstBuffer->mnHeight]); |
302 | 6.75k | } |
303 | 6.75k | catch( const std::bad_alloc& ) |
304 | 6.75k | { |
305 | | // memory exception, clean up |
306 | | // remark: the buffer ptr causing the exception |
307 | | // is still NULL here |
308 | 0 | return std::nullopt; |
309 | 0 | } |
310 | | |
311 | | // horizontal mapping table |
312 | 6.75k | if( (pDstBuffer->mnWidth != rTwoRect.mnSrcWidth) && (pDstBuffer->mnWidth != 0) ) |
313 | 0 | { |
314 | 0 | const double fFactorX = static_cast<double>(rTwoRect.mnSrcWidth) / pDstBuffer->mnWidth; |
315 | |
|
316 | 0 | for (tools::Long i = 0; i < pDstBuffer->mnWidth; ++i) |
317 | 0 | pMapX[ i ] = rTwoRect.mnSrcX + static_cast<int>( i * fFactorX ); |
318 | 0 | } |
319 | 6.75k | else |
320 | 6.75k | { |
321 | 60.7k | for (tools::Long i = 0, nTmp = rTwoRect.mnSrcX ; i < pDstBuffer->mnWidth; ++i) |
322 | 54.0k | pMapX[ i ] = nTmp++; |
323 | 6.75k | } |
324 | | |
325 | | // vertical mapping table |
326 | 6.75k | if( (pDstBuffer->mnHeight != rTwoRect.mnSrcHeight) && (pDstBuffer->mnHeight != 0) ) |
327 | 0 | { |
328 | 0 | const double fFactorY = static_cast<double>(rTwoRect.mnSrcHeight) / pDstBuffer->mnHeight; |
329 | |
|
330 | 0 | for (tools::Long i = 0; i < pDstBuffer->mnHeight; ++i) |
331 | 0 | pMapY[ i ] = rTwoRect.mnSrcY + static_cast<int>( i * fFactorY ); |
332 | 0 | } |
333 | 6.75k | else |
334 | 6.75k | { |
335 | 60.7k | for (tools::Long i = 0, nTmp = rTwoRect.mnSrcY; i < pDstBuffer->mnHeight; ++i) |
336 | 54.0k | pMapY[ i ] = nTmp++; |
337 | 6.75k | } |
338 | | |
339 | | // source scanline buffer |
340 | 6.75k | Scanline pTmpScan; |
341 | 6.75k | tools::Long nOffset; |
342 | 6.75k | if (rSrcBuffer.meDirection == ScanlineDirection::TopDown) |
343 | 6.75k | { |
344 | 6.75k | pTmpScan = rSrcBuffer.mpBits; |
345 | 6.75k | nOffset = rSrcBuffer.mnScanlineSize; |
346 | 6.75k | } |
347 | 0 | else |
348 | 0 | { |
349 | 0 | pTmpScan = rSrcBuffer.mpBits + ( rSrcBuffer.mnHeight - 1 ) * rSrcBuffer.mnScanlineSize; |
350 | 0 | nOffset = -rSrcBuffer.mnScanlineSize; |
351 | 0 | } |
352 | | |
353 | 60.7k | for (tools::Long i = 0; i < rSrcBuffer.mnHeight; i++, pTmpScan += nOffset) |
354 | 54.0k | pSrcScan[ i ] = pTmpScan; |
355 | | |
356 | | // destination scanline buffer |
357 | 6.75k | if (pDstBuffer->meDirection == ScanlineDirection::TopDown) |
358 | 6.75k | { |
359 | 6.75k | pTmpScan = pDstBuffer->mpBits; |
360 | 6.75k | nOffset = pDstBuffer->mnScanlineSize; |
361 | 6.75k | } |
362 | 0 | else |
363 | 0 | { |
364 | 0 | pTmpScan = pDstBuffer->mpBits + ( pDstBuffer->mnHeight - 1 ) * pDstBuffer->mnScanlineSize; |
365 | 0 | nOffset = -pDstBuffer->mnScanlineSize; |
366 | 0 | } |
367 | | |
368 | 60.7k | for (tools::Long i = 0; i < pDstBuffer->mnHeight; i++, pTmpScan += nOffset) |
369 | 54.0k | pDstScan[ i ] = pTmpScan; |
370 | | |
371 | | // do buffer scaling and conversion |
372 | 6.75k | if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount <= 8 ) |
373 | 0 | { |
374 | 0 | ImplPALToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel, |
375 | 0 | pSrcScan.get(), pDstScan.get(), pMapX.get(), pMapY.get() ); |
376 | 0 | } |
377 | 6.75k | else if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount > 8 ) |
378 | 6.75k | { |
379 | 6.75k | ImplPALToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel, |
380 | 6.75k | pSrcScan.get(), pDstScan.get(), pMapX.get(), pMapY.get() ); |
381 | 6.75k | } |
382 | 0 | else if( rSrcBuffer.mnBitCount > 8 && pDstBuffer->mnBitCount > 8 ) |
383 | 0 | { |
384 | 0 | ImplTCToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel, |
385 | 0 | pSrcScan.get(), pDstScan.get(), pMapX.get(), pMapY.get() ); |
386 | 0 | } |
387 | 0 | else |
388 | 0 | { |
389 | 0 | ImplTCToPAL( *pDstBuffer, pFncGetPixel, pFncSetPixel, |
390 | 0 | pSrcScan.get(), pDstScan.get(), pMapX.get(), pMapY.get() ); |
391 | 0 | } |
392 | | |
393 | 6.75k | return pDstBuffer; |
394 | 6.75k | } |
395 | | |
396 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |