Line data Source code
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 : #ifndef INCLUDED_CANVAS_CANVASTOOLS_HXX
21 : #define INCLUDED_CANVAS_CANVASTOOLS_HXX
22 :
23 : #include <rtl/math.hxx>
24 : #include <com/sun/star/uno/Reference.hxx>
25 : #include <com/sun/star/uno/Sequence.hxx>
26 : #include <com/sun/star/uno/RuntimeException.hpp>
27 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
28 : #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
29 : #include <osl/diagnose.h>
30 : #include <rtl/ustring.hxx>
31 :
32 : #include <string.h>
33 : #include <vector>
34 : #include <limits>
35 : #include <algorithm>
36 :
37 : #include <canvas/canvastoolsdllapi.h>
38 :
39 : namespace basegfx
40 : {
41 : class B2DHomMatrix;
42 : class B2DRange;
43 : class B2IRange;
44 : class B2IPoint;
45 : class B2DPolyPolygon;
46 : }
47 :
48 : namespace com { namespace sun { namespace star { namespace geometry
49 : {
50 : struct RealSize2D;
51 : struct IntegerSize2D;
52 : struct AffineMatrix2D;
53 : struct Matrix2D;
54 : } } } }
55 :
56 : namespace com { namespace sun { namespace star { namespace rendering
57 : {
58 : struct RenderState;
59 : struct ViewState;
60 : struct IntegerBitmapLayout;
61 : class XCanvas;
62 : struct Texture;
63 : class XIntegerBitmapColorSpace;
64 : class XPolyPolygon2D;
65 :
66 : bool operator==( const RenderState& rLHS,
67 : const RenderState& rRHS );
68 :
69 : bool operator==( const ViewState& rLHS,
70 : const ViewState& rRHS );
71 : } } } }
72 :
73 : namespace com { namespace sun { namespace star { namespace awt
74 : {
75 : struct Rectangle;
76 : class XWindow2;
77 : } } } }
78 :
79 : class Color;
80 :
81 : namespace canvas
82 : {
83 : namespace tools
84 : {
85 : /** Compute the next highest power of 2 of a 32-bit value
86 :
87 : Code devised by Sean Anderson, in good ole HAKMEM
88 : tradition.
89 :
90 : @return 1 << (lg(x - 1) + 1)
91 : */
92 0 : inline sal_uInt32 nextPow2( sal_uInt32 x )
93 : {
94 0 : --x;
95 0 : x |= x >> 1;
96 0 : x |= x >> 2;
97 0 : x |= x >> 4;
98 0 : x |= x >> 8;
99 0 : x |= x >> 16;
100 :
101 0 : return ++x;
102 : }
103 :
104 : /**
105 : *
106 : * Count the number of 1-bits of an n-bit value
107 : *
108 : */
109 :
110 : // mickey's math tricks...
111 : inline unsigned int pow2( unsigned int c ) { return 0x1 << c; }
112 : inline unsigned int mask( unsigned int c ) { return ((unsigned int)(-1)) / (pow2(pow2(c)) + 1); }
113 : inline unsigned int count( unsigned int x, unsigned int c ) { return ((x) & mask(c)) + (((x) >> (pow2(c))) & mask(c)); }
114 : template<typename T>
115 : inline unsigned int bitcount( T c ) {
116 : unsigned int nByteIndex = 0;
117 : unsigned int nNumBytes = sizeof(T)<<2;
118 : do {
119 : c=count(c,nByteIndex++);
120 : nNumBytes >>= 1;
121 : } while(nNumBytes);
122 : return c;
123 : }
124 : inline sal_uInt32 bitcount32( sal_uInt32 c ) {
125 : c=count(c,0);
126 : c=count(c,1);
127 : c=count(c,2);
128 : c=count(c,3);
129 : c=count(c,4);
130 : return c;
131 : }
132 :
133 : /** Round given floating point value down to next integer
134 : */
135 0 : inline sal_Int32 roundDown( const double& rVal )
136 : {
137 0 : return static_cast< sal_Int32 >( floor( rVal ) );
138 : }
139 :
140 : /** Round given floating point value up to next integer
141 : */
142 0 : inline sal_Int32 roundUp( const double& rVal )
143 : {
144 0 : return static_cast< sal_Int32 >( ceil( rVal ) );
145 : }
146 :
147 : /** Create a RealSize2D with both coordinate values set to +infinity
148 : */
149 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::geometry::RealSize2D createInfiniteSize2D();
150 :
151 :
152 : // View- and RenderState utilities
153 :
154 :
155 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::rendering::RenderState&
156 : initRenderState( ::com::sun::star::rendering::RenderState& renderState );
157 :
158 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::rendering::ViewState&
159 : initViewState( ::com::sun::star::rendering::ViewState& viewState );
160 :
161 : CANVASTOOLS_DLLPUBLIC ::basegfx::B2DHomMatrix&
162 : getViewStateTransform( ::basegfx::B2DHomMatrix& transform,
163 : const ::com::sun::star::rendering::ViewState& viewState );
164 :
165 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::rendering::ViewState&
166 : setViewStateTransform( ::com::sun::star::rendering::ViewState& viewState,
167 : const ::basegfx::B2DHomMatrix& transform );
168 :
169 : CANVASTOOLS_DLLPUBLIC ::basegfx::B2DHomMatrix&
170 : getRenderStateTransform( ::basegfx::B2DHomMatrix& transform,
171 : const ::com::sun::star::rendering::RenderState& renderState );
172 :
173 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::rendering::RenderState&
174 : setRenderStateTransform( ::com::sun::star::rendering::RenderState& renderState,
175 : const ::basegfx::B2DHomMatrix& transform );
176 :
177 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::rendering::RenderState&
178 : appendToRenderState( ::com::sun::star::rendering::RenderState& renderState,
179 : const ::basegfx::B2DHomMatrix& transform );
180 :
181 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::rendering::RenderState&
182 : prependToRenderState( ::com::sun::star::rendering::RenderState& renderState,
183 : const ::basegfx::B2DHomMatrix& transform );
184 :
185 : CANVASTOOLS_DLLPUBLIC ::basegfx::B2DHomMatrix&
186 : mergeViewAndRenderTransform( ::basegfx::B2DHomMatrix& transform,
187 : const ::com::sun::star::rendering::ViewState& viewState,
188 : const ::com::sun::star::rendering::RenderState& renderState );
189 :
190 :
191 : // Matrix utilities
192 :
193 :
194 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::geometry::AffineMatrix2D&
195 : setIdentityAffineMatrix2D( ::com::sun::star::geometry::AffineMatrix2D& matrix );
196 :
197 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::geometry::Matrix2D&
198 : setIdentityMatrix2D( ::com::sun::star::geometry::Matrix2D& matrix );
199 :
200 :
201 : // Special utilities
202 :
203 :
204 : /** Calc the bounding rectangle of a transformed rectangle.
205 :
206 : The method applies the given transformation to the
207 : specified input rectangle, and returns the bounding box of
208 : the resulting output area.
209 :
210 : @param o_Rect
211 : Output rectangle
212 :
213 : @param i_Rect
214 : Input rectangle
215 :
216 : @param i_Transformation
217 : Transformation to apply to the input rectangle
218 :
219 : @return a reference to the resulting rectangle
220 : */
221 : CANVASTOOLS_DLLPUBLIC ::basegfx::B2DRange& calcTransformedRectBounds( ::basegfx::B2DRange& o_Rect,
222 : const ::basegfx::B2DRange& i_Rect,
223 : const ::basegfx::B2DHomMatrix& i_Transformation );
224 :
225 : /** Calc a transform that maps the upper, left corner of a
226 : rectangle to the origin.
227 :
228 : The method is a specialized version of
229 : calcRectToRectTransform() (Removed now), mapping the input rectangle's
230 : the upper, left corner to the origin, and leaving the size
231 : untouched.
232 :
233 : @param o_transform
234 : Output parameter, to receive the resulting transformation
235 : matrix.
236 :
237 : @param i_srcRect
238 : Input parameter, specifies the original source
239 : rectangle. The resulting transformation will exactly map
240 : the source rectangle's upper, left corner to the origin.
241 :
242 : @param i_transformation
243 : The original transformation matrix. This is changed with
244 : translations (if necessary), to exactly map the source
245 : rectangle to the origin.
246 :
247 : @return a reference to the resulting transformation matrix
248 :
249 : @see calcRectToRectTransform()
250 : @see calcTransformedRectBounds()
251 : */
252 : CANVASTOOLS_DLLPUBLIC ::basegfx::B2DHomMatrix& calcRectToOriginTransform( ::basegfx::B2DHomMatrix& o_transform,
253 : const ::basegfx::B2DRange& i_srcRect,
254 : const ::basegfx::B2DHomMatrix& i_transformation );
255 :
256 : /** Check whether a given rectangle is within another
257 : transformed rectangle.
258 :
259 : This method checks for polygonal containedness, i.e. the
260 : transformed rectangle is not represented as an axis-alignd
261 : rectangle anymore (like calcTransformedRectBounds()), but
262 : polygonal. Thus, the insideness test is based on tight
263 : bounds.
264 :
265 : @param rContainedRect
266 : This rectangle is checked, whether it is fully within the
267 : transformed rTransformRect.
268 :
269 : @param rTransformRect
270 : This rectangle is transformed, and then checked whether it
271 : fully contains rContainedRect.
272 :
273 : @param rTransformation
274 : This transformation is applied to rTransformRect
275 : */
276 : CANVASTOOLS_DLLPUBLIC bool isInside( const ::basegfx::B2DRange& rContainedRect,
277 : const ::basegfx::B2DRange& rTransformRect,
278 : const ::basegfx::B2DHomMatrix& rTransformation );
279 :
280 : /** Clip a scroll to the given bound rect
281 :
282 : @param io_rSourceArea
283 : Source area to scroll. The resulting clipped source area
284 : is returned therein.
285 :
286 : @param io_rDestPoint
287 : Destination point of the scroll (upper, left corner of
288 : rSourceArea after the scroll). The new, resulting
289 : destination point is returned therein.q
290 :
291 : @param o_ClippedAreas
292 : Vector of rectangles in the <em>destination</em> area
293 : coordinate system, which are clipped away from the source
294 : area, and thus need extra updates (i.e. they are not
295 : correctly copy from the scroll operation, since there was
296 : no information about them in the source).
297 :
298 : @param rBounds
299 : Bounds to clip against.
300 :
301 : @return false, if the resulting scroll area is empty
302 : */
303 : CANVASTOOLS_DLLPUBLIC bool clipScrollArea( ::basegfx::B2IRange& io_rSourceArea,
304 : ::basegfx::B2IPoint& io_rDestPoint,
305 : ::std::vector< ::basegfx::B2IRange >& o_ClippedAreas,
306 : const ::basegfx::B2IRange& rBounds );
307 :
308 : /** Clip a blit between two differently surfaces.
309 :
310 : This method clips source and dest rect for a clip between
311 : two differently clipped surfaces, such that the resulting
312 : blit rects are fully within both clip areas.
313 :
314 : @param io_rSourceArea
315 : Source area of the blit. Returned therein is the computed
316 : clipped source area.
317 :
318 : @param io_rDestPoint
319 : Dest area of the blit. Returned therein is the computed
320 : clipped dest area.
321 :
322 : @param rSourceBounds
323 : Clip bounds of the source surface
324 :
325 : @param rDestBounds
326 : Clip bounds of the dest surface
327 :
328 : @return false, if the resulting blit is empty, i.e. fully
329 : clipped away.
330 : */
331 : CANVASTOOLS_DLLPUBLIC ::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange );
332 :
333 : /** Retrieve various internal properties of the actual canvas implementation.
334 :
335 : This method retrieves a bunch of internal, implementation-
336 : and platform-dependent values from the canvas
337 : implementation. Among them are for example operating
338 : system window handles. The actual layout and content of
339 : the returned sequence is dependent on the component
340 : implementation, undocumented and subject to change.
341 :
342 : @param i_rxCanvas
343 : Input parameter, the canvas representation for which the device information
344 : is to be retrieveds
345 :
346 : @param o_rxParams
347 : Output parameter, the sequence of Anys that hold the device parameters. Layout is as described above
348 :
349 : @return A reference to the resulting sequence of parameters
350 : */
351 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& getDeviceInfo(
352 : const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas >& i_rxCanvas,
353 : ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& o_rxParams );
354 :
355 : /** Return a color space for a default RGBA integer format
356 :
357 : Use this method for dead-simple bitmap implementations,
358 : that map all their formats to 8888 RGBA color.
359 : */
360 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XIntegerBitmapColorSpace> getStdColorSpace();
361 :
362 : /** Return a color space for a default RGB integer format
363 :
364 : Use this method for dead-simple bitmap implementations,
365 : that map all their formats to 8888 RGB color (the last byte
366 : is unused).
367 : */
368 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XIntegerBitmapColorSpace> getStdColorSpaceWithoutAlpha();
369 :
370 : /** Return a memory layout for a default RGBA integer format
371 :
372 : Use this method for dead-simple bitmap implementations,
373 : that map all their formats to 8888 RGBA color.
374 : */
375 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::rendering::IntegerBitmapLayout getStdMemoryLayout(
376 : const ::com::sun::star::geometry::IntegerSize2D& rBitmapSize );
377 :
378 : /// Convert standard 8888 RGBA color to vcl color
379 : CANVASTOOLS_DLLPUBLIC ::Color stdIntSequenceToColor( const ::com::sun::star::uno::Sequence<sal_Int8>& rColor );
380 :
381 : /// Convert standard 8888 RGBA color to vcl color
382 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::uno::Sequence<sal_Int8> colorToStdIntSequence( const ::Color& rColor );
383 :
384 : // Modelled closely after boost::numeric_cast, only that we
385 : // issue some trace output here and throw a RuntimeException
386 :
387 : /** Cast numeric value into another (numeric) data type
388 :
389 : Apart from converting the numeric value, this template
390 : also checks if any overflow, underflow, or sign
391 : information is lost (if yes, it throws an
392 : uno::RuntimeException.
393 : */
394 0 : template< typename Target, typename Source > inline Target numeric_cast( Source arg )
395 : {
396 : // typedefs abbreviating respective trait classes
397 : typedef ::std::numeric_limits< Source > SourceLimits;
398 : typedef ::std::numeric_limits< Target > TargetLimits;
399 :
400 : #undef min
401 : #undef max
402 :
403 0 : if( ( arg<0 && !TargetLimits::is_signed) || // losing the sign here
404 0 : ( SourceLimits::is_signed && arg<TargetLimits::min()) || // underflow will happen
405 0 : ( arg>TargetLimits::max() ) ) // overflow will happen
406 : {
407 : # if OSL_DEBUG_LEVEL > 2
408 : OSL_TRACE("numeric_cast detected data loss");
409 : #endif
410 0 : throw ::com::sun::star::uno::RuntimeException(
411 : "numeric_cast detected data loss",
412 0 : NULL );
413 : }
414 :
415 0 : return static_cast<Target>(arg);
416 : }
417 :
418 : CANVASTOOLS_DLLPUBLIC ::com::sun::star::awt::Rectangle getAbsoluteWindowRect(
419 : const ::com::sun::star::awt::Rectangle& rRect,
420 : const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow2 >& xWin );
421 :
422 : /** Retrieve for small bound marks around each corner of the given rectangle
423 : */
424 : CANVASTOOLS_DLLPUBLIC ::basegfx::B2DPolyPolygon getBoundMarksPolyPolygon( const ::basegfx::B2DRange& rRange );
425 :
426 : /** Calculate number of gradient "strips" to generate (takes
427 : into account device resolution)
428 :
429 : @param nColorSteps
430 : Maximal integer difference between all color stops, needed
431 : for smooth gradient color differences
432 : */
433 : CANVASTOOLS_DLLPUBLIC int calcGradientStepCount( ::basegfx::B2DHomMatrix& rTotalTransform,
434 : const ::com::sun::star::rendering::ViewState& viewState,
435 : const ::com::sun::star::rendering::RenderState& renderState,
436 : const ::com::sun::star::rendering::Texture& texture,
437 : int nColorSteps );
438 :
439 : /** A very simplistic map for ASCII strings and arbitrary value
440 : types.
441 :
442 : This class internally references a constant, static array of
443 : sorted MapEntries, and performs a binary search to look up
444 : values for a given query string. Note that this map is static,
445 : i.e. not meant to be extented at runtime.
446 :
447 : @tpl ValueType
448 : The value type this map should store, associated with an ASCII
449 : string.
450 : */
451 : template< typename ValueType > class ValueMap
452 : {
453 : public:
454 76 : struct MapEntry
455 : {
456 : const char* maKey;
457 : ValueType maValue;
458 : };
459 :
460 : /** Create a ValueMap for the given array of MapEntries.
461 :
462 : @param pMap
463 : Pointer to a <em>static</em> array of MapEntries. Must
464 : live longer than this object! Make absolutely sure that
465 : the string entries passed via pMap are ASCII-only -
466 : everything else might not yield correct string
467 : comparisons, and thus will result in undefined behaviour.
468 :
469 : @param nEntries
470 : Number of entries for pMap
471 :
472 : @param bCaseSensitive
473 : Whether the map query should be performed case sensitive
474 : or not. When bCaseSensitive is false, all MapEntry strings
475 : must be lowercase!
476 : */
477 2 : ValueMap( const MapEntry* pMap,
478 : ::std::size_t nEntries,
479 : bool bCaseSensitive ) :
480 : mpMap( pMap ),
481 : mnEntries( nEntries ),
482 2 : mbCaseSensitive( bCaseSensitive )
483 : {
484 : #ifdef DBG_UTIL
485 : // Ensure that map entries are sorted (and all lowercase, if this
486 : // map is case insensitive)
487 : const OString aStr( pMap->maKey );
488 : if( !mbCaseSensitive &&
489 : aStr != aStr.toAsciiLowerCase() )
490 : {
491 : OSL_TRACE("ValueMap::ValueMap(): Key %s is not lowercase",
492 : pMap->maKey);
493 : OSL_FAIL( "ValueMap::ValueMap(): Key is not lowercase" );
494 : }
495 :
496 : if( mnEntries > 1 )
497 : {
498 : for( ::std::size_t i=0; i<mnEntries-1; ++i, ++pMap )
499 : {
500 : if( !mapComparator(pMap[0], pMap[1]) &&
501 : mapComparator(pMap[1], pMap[0]) )
502 : {
503 : OSL_TRACE("ValueMap::ValueMap(): Map is not sorted, keys %s and %s are wrong",
504 : pMap[0].maKey,
505 : pMap[1].maKey);
506 : OSL_FAIL( "ValueMap::ValueMap(): Map is not sorted" );
507 : }
508 :
509 : const OString aStr2( pMap[1].maKey );
510 : if( !mbCaseSensitive &&
511 : aStr2 != aStr2.toAsciiLowerCase() )
512 : {
513 : OSL_TRACE("ValueMap::ValueMap(): Key %s is not lowercase",
514 : pMap[1].maKey);
515 : OSL_FAIL( "ValueMap::ValueMap(): Key is not lowercase" );
516 : }
517 : }
518 : }
519 : #endif
520 2 : }
521 :
522 : /** Lookup a value for the given query string
523 :
524 : @param rName
525 : The string to lookup. If the map was created with the case
526 : insensitive flag, the lookup is performed
527 : case-insensitive, otherwise, case-sensitive.
528 :
529 : @param o_rResult
530 : Output parameter, which receives the value associated with
531 : the query string. If no value was found, the referenced
532 : object is kept unmodified.
533 :
534 : @return true, if a matching entry was found.
535 : */
536 0 : bool lookup( const OUString& rName,
537 : ValueType& o_rResult ) const
538 : {
539 : // rName is required to contain only ASCII characters.
540 : // TODO(Q1): Enforce this at upper layers
541 : OString aKey( OUStringToOString( mbCaseSensitive ? rName : rName.toAsciiLowerCase(),
542 0 : RTL_TEXTENCODING_ASCII_US ) );
543 : MapEntry aSearchKey =
544 : {
545 0 : aKey.getStr(),
546 : ValueType()
547 0 : };
548 :
549 : const MapEntry* pRes;
550 0 : const MapEntry* pEnd = mpMap+mnEntries;
551 0 : if( (pRes=::std::lower_bound( mpMap,
552 : pEnd,
553 : aSearchKey,
554 0 : &mapComparator )) != pEnd )
555 : {
556 : // place to _insert before_ found - is it equal to
557 : // the search key?
558 0 : if( strcmp( pRes->maKey, aSearchKey.maKey ) == 0 )
559 : {
560 : // yep, correct entry found
561 0 : o_rResult = pRes->maValue;
562 0 : return true;
563 : }
564 : }
565 :
566 : // not found
567 0 : return false;
568 : }
569 :
570 : private:
571 0 : static bool mapComparator( const MapEntry& rLHS,
572 : const MapEntry& rRHS )
573 : {
574 : return strcmp( rLHS.maKey,
575 0 : rRHS.maKey ) < 0;
576 : }
577 :
578 : const MapEntry* mpMap;
579 : ::std::size_t mnEntries;
580 : bool mbCaseSensitive;
581 : };
582 : }
583 : }
584 :
585 : #endif /* INCLUDED_CANVAS_CANVASTOOLS_HXX */
586 :
587 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|