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