Update ooo320-m1
[ooovba.git] / vcl / source / gdi / octree.cxx
blob9e1826ee30b685057c7695136971c2e7fe676d5c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: octree.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <limits.h>
34 #include <vcl/bmpacc.hxx>
35 #include <vcl/impoct.hxx>
36 #include <vcl/octree.hxx>
38 // ---------
39 // - pMask -
40 // ---------
42 static BYTE pImplMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
44 // -------------
45 // - NodeCache -
46 // -------------
48 ImpNodeCache::ImpNodeCache( const ULONG nInitSize ) :
49 pActNode( NULL )
51 const ULONG nSize = nInitSize + 4;
53 for( ULONG i = 0; i < nSize; i++ )
55 OctreeNode* pNewNode = new NODE;
57 pNewNode->pNextInCache = pActNode;
58 pActNode = pNewNode;
62 // ------------------------------------------------------------------------
64 ImpNodeCache::~ImpNodeCache()
66 while( pActNode )
68 OctreeNode* pNode = pActNode;
70 pActNode = pNode->pNextInCache;
71 delete pNode;
75 // ----------
76 // - Octree -
77 // ----------
79 Octree::Octree( ULONG nColors ) :
80 nMax ( nColors ),
81 nLeafCount ( 0L ),
82 pTree ( NULL ),
83 pAcc ( NULL )
85 pNodeCache = new ImpNodeCache( nColors );
86 memset( pReduce, 0, ( OCTREE_BITS + 1 ) * sizeof( PNODE ) );
89 // ------------------------------------------------------------------------
91 Octree::Octree( const BitmapReadAccess& rReadAcc, ULONG nColors ) :
92 nMax ( nColors ),
93 nLeafCount ( 0L ),
94 pTree ( NULL ),
95 pAcc ( &rReadAcc )
97 pNodeCache = new ImpNodeCache( nColors );
98 memset( pReduce, 0, ( OCTREE_BITS + 1 ) * sizeof( PNODE ) );
99 ImplCreateOctree();
102 // ------------------------------------------------------------------------
104 Octree::~Octree()
106 ImplDeleteOctree( &pTree );
107 delete pNodeCache;
110 // ------------------------------------------------------------------------
112 void Octree::AddColor( const BitmapColor& rColor )
114 pColor = &(BitmapColor&) rColor;
115 nLevel = 0L;
116 ImplAdd( &pTree );
118 while( nLeafCount > nMax )
119 ImplReduce();
122 // ------------------------------------------------------------------------
124 void Octree::ImplCreateOctree()
126 if( !!*pAcc )
128 const long nWidth = pAcc->Width();
129 const long nHeight = pAcc->Height();
131 if( pAcc->HasPalette() )
133 for( long nY = 0; nY < nHeight; nY++ )
135 for( long nX = 0; nX < nWidth; nX++ )
137 pColor = &(BitmapColor&) pAcc->GetPaletteColor( pAcc->GetPixel( nY, nX ) );
138 nLevel = 0L;
139 ImplAdd( &pTree );
141 while( nLeafCount > nMax )
142 ImplReduce();
146 else
148 BitmapColor aColor;
150 pColor = &aColor;
152 for( long nY = 0; nY < nHeight; nY++ )
154 for( long nX = 0; nX < nWidth; nX++ )
156 aColor = pAcc->GetPixel( nY, nX );
157 nLevel = 0L;
158 ImplAdd( &pTree );
160 while( nLeafCount > nMax )
161 ImplReduce();
168 // ------------------------------------------------------------------------
170 void Octree::ImplDeleteOctree( PPNODE ppNode )
172 for ( ULONG i = 0UL; i < 8UL; i++ )
174 if ( (*ppNode)->pChild[ i ] )
175 ImplDeleteOctree( &(*ppNode)->pChild[ i ] );
178 pNodeCache->ImplReleaseNode( *ppNode );
179 *ppNode = NULL;
182 // ------------------------------------------------------------------------
184 void Octree::ImplAdd( PPNODE ppNode )
186 // ggf. neuen Knoten erzeugen
187 if( !*ppNode )
189 *ppNode = pNodeCache->ImplGetFreeNode();
190 (*ppNode)->bLeaf = ( OCTREE_BITS == nLevel );
192 if( (*ppNode)->bLeaf )
193 nLeafCount++;
194 else
196 (*ppNode)->pNext = pReduce[ nLevel ];
197 pReduce[ nLevel ] = *ppNode;
201 if( (*ppNode)->bLeaf )
203 (*ppNode)->nCount++;
204 (*ppNode)->nRed += pColor->GetRed();
205 (*ppNode)->nGreen += pColor->GetGreen();
206 (*ppNode)->nBlue += pColor->GetBlue();
208 else
210 const ULONG nShift = 7 - nLevel;
211 const BYTE cMask = pImplMask[ nLevel ];
212 const ULONG nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
213 ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
214 ( ( pColor->GetBlue() & cMask ) >> nShift );
216 nLevel++;
217 ImplAdd( &(*ppNode)->pChild[ nIndex ] );
221 // ------------------------------------------------------------------------
223 void Octree::ImplReduce()
225 ULONG i;
226 PNODE pNode;
227 ULONG nRedSum = 0L;
228 ULONG nGreenSum = 0L;
229 ULONG nBlueSum = 0L;
230 ULONG nChilds = 0L;
232 for ( i = OCTREE_BITS - 1; i && !pReduce[i]; i-- ) {}
234 pNode = pReduce[ i ];
235 pReduce[ i ] = pNode->pNext;
237 for ( i = 0; i < 8; i++ )
239 if ( pNode->pChild[ i ] )
241 PNODE pChild = pNode->pChild[ i ];
243 nRedSum += pChild->nRed;
244 nGreenSum += pChild->nGreen;
245 nBlueSum += pChild->nBlue;
246 pNode->nCount += pChild->nCount;
248 pNodeCache->ImplReleaseNode( pNode->pChild[ i ] );
249 pNode->pChild[ i ] = NULL;
250 nChilds++;
254 pNode->bLeaf = TRUE;
255 pNode->nRed = nRedSum;
256 pNode->nGreen = nGreenSum;
257 pNode->nBlue = nBlueSum;
258 nLeafCount -= --nChilds;
261 // ------------------------------------------------------------------------
263 void Octree::CreatePalette( PNODE pNode )
265 if( pNode->bLeaf )
267 pNode->nPalIndex = nPalIndex;
268 aPal[ nPalIndex++ ] = BitmapColor( (BYTE) ( (double) pNode->nRed / pNode->nCount ),
269 (BYTE) ( (double) pNode->nGreen / pNode->nCount ),
270 (BYTE) ( (double) pNode->nBlue / pNode->nCount ) );
272 else for( ULONG i = 0UL; i < 8UL; i++ )
273 if( pNode->pChild[ i ] )
274 CreatePalette( pNode->pChild[ i ] );
278 // ------------------------------------------------------------------------
280 void Octree::GetPalIndex( PNODE pNode )
282 if ( pNode->bLeaf )
283 nPalIndex = pNode->nPalIndex;
284 else
286 const ULONG nShift = 7 - nLevel;
287 const BYTE cMask = pImplMask[ nLevel++ ];
288 const ULONG nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
289 ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
290 ( ( pColor->GetBlue() & cMask ) >> nShift );
292 GetPalIndex( pNode->pChild[ nIndex ] );
296 // -------------------
297 // - InverseColorMap -
298 // -------------------
300 InverseColorMap::InverseColorMap( const BitmapPalette& rPal ) :
301 nBits( 8 - OCTREE_BITS )
303 ULONG* cdp;
304 BYTE* crgbp;
305 const ULONG nColorMax = 1 << OCTREE_BITS;
306 const ULONG xsqr = 1 << ( nBits << 1 );
307 const ULONG xsqr2 = xsqr << 1;
308 const ULONG nColors = rPal.GetEntryCount();
309 const long x = 1L << nBits;
310 const long x2 = x >> 1L;
311 ULONG r, g, b;
312 long rxx, gxx, bxx;
313 long rdist, gdist, bdist;
314 long crinc, cginc, cbinc;
316 ImplCreateBuffers( nColorMax );
318 for( ULONG nIndex = 0; nIndex < nColors; nIndex++ )
320 const BitmapColor& rColor = rPal[ (USHORT) nIndex ];
321 const BYTE cRed = rColor.GetRed();
322 const BYTE cGreen = rColor.GetGreen();
323 const BYTE cBlue = rColor.GetBlue();
325 rdist = cRed - x2;
326 gdist = cGreen - x2;
327 bdist = cBlue - x2;
328 rdist = rdist*rdist + gdist*gdist + bdist*bdist;
330 crinc = ( xsqr - ( cRed << nBits ) ) << 1L;
331 cginc = ( xsqr - ( cGreen << nBits ) ) << 1L;
332 cbinc = ( xsqr - ( cBlue << nBits ) ) << 1L;
334 cdp = (ULONG*) pBuffer;
335 crgbp = pMap;
337 for( r = 0, rxx = crinc; r < nColorMax; rdist += rxx, r++, rxx += xsqr2 )
339 for( g = 0, gdist = rdist, gxx = cginc; g < nColorMax; gdist += gxx, g++, gxx += xsqr2 )
341 for( b = 0, bdist = gdist, bxx = cbinc; b < nColorMax; bdist += bxx, b++, cdp++, crgbp++, bxx += xsqr2 )
342 if ( !nIndex || ( (long) *cdp ) > bdist )
344 *cdp = bdist;
345 *crgbp = (BYTE) nIndex;
352 // ------------------------------------------------------------------------
354 InverseColorMap::~InverseColorMap()
356 rtl_freeMemory( pBuffer );
357 rtl_freeMemory( pMap );
360 // ------------------------------------------------------------------------
362 void InverseColorMap::ImplCreateBuffers( const ULONG nMax )
364 const ULONG nCount = nMax * nMax * nMax;
365 const ULONG nSize = nCount * sizeof( ULONG );
367 pMap = (BYTE*) rtl_allocateMemory( nCount );
368 memset( pMap, 0x00, nCount );
370 pBuffer = (BYTE*) rtl_allocateMemory( nSize );
371 memset( pBuffer, 0xff, nSize );