Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "swfwriter.hxx"
30 : : #include <vcl/virdev.hxx>
31 : : #include <basegfx/matrix/b2dhommatrixtools.hxx>
32 : :
33 : : #include <math.h>
34 : :
35 : : using namespace ::swf;
36 : : using namespace ::std;
37 : : using namespace ::com::sun::star::uno;
38 : : using namespace ::com::sun::star::io;
39 : : using ::rtl::OUString;
40 : : using ::rtl::OString;
41 : :
42 : : // -----------------------------------------------------------------------------
43 : :
44 : 0 : sal_uInt16 getMaxBitsUnsigned( sal_uInt32 nValue )
45 : : {
46 : 0 : sal_uInt16 nBits = 0;
47 : :
48 : 0 : while( nValue )
49 : : {
50 : 0 : nBits++;
51 : 0 : nValue >>= 1;
52 : : }
53 : :
54 : 0 : return nBits;
55 : : }
56 : :
57 : : // -----------------------------------------------------------------------------
58 : :
59 : 0 : sal_uInt16 getMaxBitsSigned( sal_Int32 nValue )
60 : : {
61 : 0 : if( nValue < 0 )
62 : 0 : nValue *= -1;
63 : :
64 : 0 : return getMaxBitsUnsigned( static_cast< sal_uInt32 >(nValue) ) + 1;
65 : : }
66 : :
67 : : // -----------------------------------------------------------------------------
68 : :
69 : 0 : BitStream::BitStream()
70 : : {
71 : 0 : mnBitPos = 8;
72 : 0 : mnCurrentByte = 0;
73 : 0 : }
74 : :
75 : : // -----------------------------------------------------------------------------
76 : :
77 : 0 : void BitStream::writeUB( sal_uInt32 nValue, sal_uInt16 nBits )
78 : : {
79 : 0 : while( nBits != 0 )
80 : : {
81 : 0 : mnCurrentByte |= nValue << (32 - nBits) >> (32 - mnBitPos);
82 : :
83 : 0 : if ( nBits > mnBitPos )
84 : : {
85 : 0 : nBits = nBits - mnBitPos;
86 : 0 : mnBitPos = 0;
87 : : }
88 : : else
89 : : {
90 : 0 : mnBitPos = sal::static_int_cast<sal_uInt8>( mnBitPos - nBits );
91 : 0 : nBits = 0;
92 : : }
93 : :
94 : 0 : if( 0 == mnBitPos )
95 : 0 : pad();
96 : : }
97 : 0 : }
98 : :
99 : : // -----------------------------------------------------------------------------
100 : :
101 : 0 : void BitStream::writeSB( sal_Int32 nValue, sal_uInt16 nBits )
102 : : {
103 : 0 : writeUB( static_cast< sal_uInt32 >(nValue), nBits );
104 : 0 : }
105 : :
106 : : // -----------------------------------------------------------------------------
107 : :
108 : 0 : void BitStream::writeFB( sal_uInt32 nValue, sal_uInt16 nBits )
109 : : {
110 : 0 : writeUB( nValue, nBits );
111 : 0 : }
112 : :
113 : : // -----------------------------------------------------------------------------
114 : :
115 : 0 : void BitStream::pad()
116 : : {
117 : 0 : if( 8 != mnBitPos )
118 : : {
119 : 0 : maData.push_back( mnCurrentByte );
120 : 0 : mnCurrentByte = 0;
121 : 0 : mnBitPos = 8;
122 : : }
123 : 0 : }
124 : :
125 : : // -----------------------------------------------------------------------------
126 : :
127 : 0 : void BitStream::writeTo( SvStream& out )
128 : : {
129 : 0 : pad();
130 : :
131 : 0 : vector< sal_uInt8 >::iterator aIter( maData.begin() );
132 : 0 : const vector< sal_uInt8>::iterator aEnd( maData.end() );
133 : 0 : while(aIter != aEnd)
134 : : {
135 : 0 : out << (*aIter++);
136 : : }
137 : 0 : }
138 : :
139 : : // -----------------------------------------------------------------------------
140 : :
141 : 0 : sal_uInt32 BitStream::getOffset() const
142 : : {
143 : 0 : return maData.size();
144 : : }
145 : :
146 : : ////////////////////////////////////////////////////////////////////////////////
147 : :
148 : 0 : Tag::Tag( sal_uInt8 nTagId )
149 : : {
150 : 0 : mnTagId = nTagId;
151 : 0 : }
152 : :
153 : : // -----------------------------------------------------------------------------
154 : :
155 : 0 : void Tag::write( SvStream &out )
156 : : {
157 : 0 : Seek( STREAM_SEEK_TO_END );
158 : 0 : sal_uInt32 nSz = Tell();
159 : 0 : Seek( STREAM_SEEK_TO_BEGIN );
160 : :
161 : 0 : if( mnTagId != 0xff )
162 : : {
163 : 0 : bool bLarge = nSz > 62;
164 : :
165 : 0 : sal_uInt16 nCode = ( mnTagId << 6 ) | ( bLarge ? 0x3f : _uInt16(nSz) );
166 : :
167 : 0 : out << (sal_uInt8)nCode;
168 : 0 : out << (sal_uInt8)(nCode >> 8);
169 : :
170 : 0 : if( bLarge )
171 : : {
172 : 0 : sal_uInt32 nTmp = nSz;
173 : :
174 : 0 : out << (sal_uInt8)nTmp;
175 : 0 : nTmp >>= 8;
176 : 0 : out << (sal_uInt8)nTmp;
177 : 0 : nTmp >>= 8;
178 : 0 : out << (sal_uInt8)nTmp;
179 : 0 : nTmp >>= 8;
180 : 0 : out << (sal_uInt8)nTmp;
181 : : }
182 : : }
183 : :
184 : 0 : out.Write( GetData(), nSz );
185 : 0 : }
186 : : #if 0
187 : : // -----------------------------------------------------------------------------
188 : :
189 : : void Tag::addI32( sal_Int32 nValue )
190 : : {
191 : : addUI32( static_cast<sal_uInt32>( nValue ) );
192 : : }
193 : : #endif
194 : : // -----------------------------------------------------------------------------
195 : :
196 : 0 : void Tag::addUI32( sal_uInt32 nValue )
197 : : {
198 : 0 : *this << nValue;
199 : 0 : }
200 : : #if 0
201 : : // -----------------------------------------------------------------------------
202 : :
203 : : void Tag::addI16( sal_Int16 nValue )
204 : : {
205 : : addUI16( static_cast<sal_uInt16>( nValue ) );
206 : : }
207 : : #endif
208 : : // -----------------------------------------------------------------------------
209 : :
210 : 0 : void Tag::addUI16( sal_uInt16 nValue )
211 : : {
212 : 0 : *this << (sal_uInt8)nValue;
213 : 0 : *this << (sal_uInt8)(nValue >> 8);
214 : 0 : }
215 : :
216 : : // -----------------------------------------------------------------------------
217 : :
218 : 0 : void Tag::addUI8( sal_uInt8 nValue )
219 : : {
220 : 0 : *this << (sal_uInt8)nValue;
221 : 0 : }
222 : :
223 : : // -----------------------------------------------------------------------------
224 : :
225 : 0 : void Tag::addBits( BitStream& rIn )
226 : : {
227 : 0 : rIn.writeTo( *this );
228 : 0 : }
229 : :
230 : : // -----------------------------------------------------------------------------
231 : :
232 : 0 : void Tag::addRGBA( const Color& rColor )
233 : : {
234 : 0 : addUI8( rColor.GetRed() );
235 : 0 : addUI8( rColor.GetGreen() );
236 : 0 : addUI8( rColor.GetBlue() );
237 : 0 : addUI8( 0xff - rColor.GetTransparency() );
238 : 0 : }
239 : :
240 : : // -----------------------------------------------------------------------------
241 : :
242 : 0 : void Tag::addRGB( const Color& rColor )
243 : : {
244 : 0 : addUI8( rColor.GetRed() );
245 : 0 : addUI8( rColor.GetGreen() );
246 : 0 : addUI8( rColor.GetBlue() );
247 : 0 : }
248 : :
249 : : // -----------------------------------------------------------------------------
250 : :
251 : 0 : void Tag::addRect( const Rectangle& rRect )
252 : : {
253 : 0 : writeRect( *this, rRect );
254 : 0 : }
255 : :
256 : : // -----------------------------------------------------------------------------
257 : :
258 : 0 : void Tag::writeRect( SvStream& rOut, const Rectangle& rRect )
259 : : {
260 : 0 : BitStream aBits;
261 : :
262 : : sal_Int32 minX, minY, maxX, maxY;
263 : :
264 : 0 : if( rRect.nLeft < rRect.nRight )
265 : : {
266 : 0 : minX = rRect.nLeft; maxX = rRect.nRight;
267 : : }
268 : : else
269 : : {
270 : 0 : maxX = rRect.nLeft; minX = rRect.nRight;
271 : : }
272 : :
273 : :
274 : 0 : if( rRect.nTop < rRect.nBottom )
275 : : {
276 : 0 : minY = rRect.nTop; maxY = rRect.nBottom;
277 : : }
278 : : else
279 : : {
280 : 0 : maxY = rRect.nTop; minY = rRect.nBottom;
281 : : }
282 : :
283 : : // AS: Figure out the maximum nubmer of bits required to represent any of the
284 : : // rectangle coordinates. Since minX or minY could be negative, they could
285 : : // actually require more bits than maxX or maxY.
286 : : // AS: Christian, can they be negative, or is that a wasted check?
287 : : // CL: I think so, f.e. for shapes that have the top and/or left edge outside
288 : : // the page origin
289 : 0 : sal_uInt8 nBits1 = sal::static_int_cast<sal_uInt8>( max( getMaxBitsSigned( minX ), getMaxBitsSigned( minY ) ) );
290 : 0 : sal_uInt8 nBits2 = sal::static_int_cast<sal_uInt8>( max( getMaxBitsSigned( maxX ), getMaxBitsSigned( maxY ) ) );
291 : 0 : sal_uInt8 nBitsMax = max( nBits1, nBits2 );
292 : :
293 : 0 : aBits.writeUB( nBitsMax, 5 );
294 : 0 : aBits.writeSB( minX, nBitsMax );
295 : 0 : aBits.writeSB( maxX, nBitsMax );
296 : 0 : aBits.writeSB( minY, nBitsMax );
297 : 0 : aBits.writeSB( maxY, nBitsMax );
298 : :
299 : 0 : aBits.writeTo( rOut );
300 : 0 : }
301 : :
302 : : // -----------------------------------------------------------------------------
303 : :
304 : 0 : void Tag::addMatrix( const ::basegfx::B2DHomMatrix& rMatrix ) // #i73264#
305 : : {
306 : 0 : writeMatrix( *this, rMatrix );
307 : 0 : }
308 : :
309 : : // -----------------------------------------------------------------------------
310 : :
311 : 0 : void Tag::writeMatrix( SvStream& rOut, const ::basegfx::B2DHomMatrix& rMatrix ) // #i73264#
312 : : {
313 : :
314 : 0 : BitStream aBits;
315 : :
316 : 0 : const sal_uInt8 bHasScale = rMatrix.get(0, 0) != 1.0 || rMatrix.get(1, 1) != 1.0;
317 : :
318 : 0 : aBits.writeUB( bHasScale, 1 );
319 : :
320 : 0 : if( bHasScale )
321 : : {
322 : 0 : sal_uInt8 nScaleBits = 31;
323 : :
324 : 0 : aBits.writeUB( nScaleBits, 5 );
325 : 0 : aBits.writeFB( getFixed( rMatrix.get(0, 0) ), nScaleBits ); // Scale X
326 : 0 : aBits.writeFB( getFixed( rMatrix.get(1, 1) ), nScaleBits ); // Scale Y
327 : : }
328 : :
329 : 0 : const sal_uInt8 bHasRotate = rMatrix.get(0, 1) != 0.0 || rMatrix.get(1, 0) != 0.0;
330 : :
331 : 0 : aBits.writeUB( bHasRotate, 1 );
332 : :
333 : 0 : if( bHasRotate )
334 : : {
335 : 0 : sal_uInt8 nRotateBits = 31;
336 : :
337 : 0 : aBits.writeUB( nRotateBits, 5 );
338 : 0 : aBits.writeFB( getFixed( rMatrix.get(0, 1) ), nRotateBits ); // RotateSkew0
339 : 0 : aBits.writeFB( getFixed( rMatrix.get(1, 0) ), nRotateBits ); // RotateSkew1
340 : : }
341 : :
342 : 0 : sal_uInt8 nTranslateBits = 16;
343 : :
344 : 0 : aBits.writeUB( nTranslateBits, 5 );
345 : 0 : aBits.writeSB( (sal_Int16)rMatrix.get(0, 2), nTranslateBits ); // Translate X
346 : 0 : aBits.writeSB( (sal_Int16)rMatrix.get(1, 2), nTranslateBits ); // Translate Y
347 : :
348 : 0 : aBits.writeTo( rOut );
349 : 0 : }
350 : :
351 : : // -----------------------------------------------------------------------------
352 : :
353 : 0 : void Tag::addString( const char* pString )
354 : : {
355 : 0 : if( pString )
356 : : {
357 : 0 : while( *pString )
358 : 0 : addUI8( *pString++ );
359 : : }
360 : :
361 : 0 : addUI8( 0 );
362 : 0 : }
363 : :
364 : : // -----------------------------------------------------------------------------
365 : :
366 : 0 : void Tag::addStream( SvStream& rIn )
367 : : {
368 : 0 : *this << rIn;
369 : 0 : }
370 : :
371 : : ////////////////////////////////////////////////////////////////////////////////
372 : :
373 : 0 : Sprite::Sprite( sal_uInt16 nId )
374 : 0 : : mnId( nId ), mnFrames(0)
375 : : {
376 : 0 : }
377 : :
378 : : // -----------------------------------------------------------------------------
379 : :
380 : 0 : Sprite::~Sprite()
381 : : {
382 : 0 : for(vector< Tag* >::iterator i = maTags.begin(); i != maTags.end(); ++i)
383 : 0 : delete *i;
384 : 0 : }
385 : :
386 : : // -----------------------------------------------------------------------------
387 : :
388 : 0 : void Sprite::write( SvStream& out )
389 : : {
390 : 0 : SvMemoryStream aTmp;
391 : 0 : for(vector< Tag* >::iterator i = maTags.begin(); i != maTags.end(); ++i)
392 : 0 : (*i)->write( aTmp );
393 : :
394 : 0 : if( !mnFrames )
395 : 0 : mnFrames = 1;
396 : :
397 : 0 : aTmp.Seek(0);
398 : :
399 : 0 : Tag aTag( TAG_DEFINESPRITE );
400 : 0 : aTag.addUI16( mnId );
401 : 0 : aTag.addUI16( _uInt16( mnFrames ) );
402 : 0 : aTag.addStream( aTmp );
403 : 0 : aTag.write( out );
404 : 0 : }
405 : :
406 : : // -----------------------------------------------------------------------------
407 : :
408 : 0 : void Sprite::addTag( Tag* pNewTag )
409 : : {
410 : 0 : if( pNewTag )
411 : : {
412 : 0 : if( pNewTag->getTagId() == TAG_SHOWFRAME )
413 : 0 : mnFrames++;
414 : :
415 : 0 : maTags.push_back( pNewTag );
416 : : }
417 : 0 : }
418 : :
419 : : /////////////////////////////////////////////////////////////////////////////////
420 : :
421 : 0 : sal_uInt32 swf::getFixed( double fValue )
422 : : {
423 : 0 : sal_Int16 nUpper = (sal_Int16)floor(fValue);
424 : 0 : sal_uInt16 nLower = (sal_uInt16)((fValue - floor(fValue))*0x10000);
425 : :
426 : 0 : sal_uInt32 temp = ((sal_Int32)nUpper)<<16;
427 : 0 : temp |= nLower;
428 : :
429 : 0 : return temp;
430 : : }
431 : :
432 : : /////////////////////////////////////////////////////////////////////////////////
433 : :
434 : : /** constructs a new flash font for the given VCL Font */
435 : 0 : FlashFont::FlashFont( const Font& rFont, sal_uInt16 nId )
436 : 0 : : maFont( rFont ), mnNextIndex(0), mnId( nId )
437 : : {
438 : 0 : }
439 : :
440 : : // -----------------------------------------------------------------------------
441 : :
442 : 0 : FlashFont::~FlashFont()
443 : : {
444 : 0 : }
445 : :
446 : : // -----------------------------------------------------------------------------
447 : :
448 : : /** gets the glyph id for the given character. The glyphs are created on demand */
449 : 0 : sal_uInt16 FlashFont::getGlyph( sal_uInt16 nChar, VirtualDevice* pVDev )
450 : : {
451 : : // see if we already created a glyph for this character
452 : 0 : std::map<sal_uInt16, sal_uInt16, ltuint16>::iterator aIter( maGlyphIndex.find(nChar) );
453 : 0 : if( aIter != maGlyphIndex.end() )
454 : : {
455 : 0 : return aIter->second;
456 : : }
457 : :
458 : : // if not, we create one now
459 : :
460 : 0 : maGlyphIndex[nChar] = mnNextIndex;
461 : :
462 : 0 : Font aOldFont( pVDev->GetFont() );
463 : 0 : Font aNewFont( aOldFont );
464 : 0 : aNewFont.SetAlign( ALIGN_BASELINE );
465 : 0 : pVDev->SetFont( aNewFont );
466 : 0 : aOldFont.SetOrientation(0);
467 : :
468 : : // let the virtual device convert the character to polygons
469 : 0 : PolyPolygon aPolyPoly;
470 : 0 : pVDev->GetTextOutline( aPolyPoly, rtl::OUString(nChar) );
471 : :
472 : 0 : maGlyphOffsets.push_back( _uInt16( maGlyphData.getOffset() ) );
473 : :
474 : : // Number of fill and line index bits set to 1
475 : 0 : maGlyphData.writeUB( 0x11, 8 );
476 : :
477 : 0 : const sal_uInt16 nCount = aPolyPoly.Count();
478 : : sal_uInt16 i,n;
479 : 0 : for( i = 0; i < nCount; i++ )
480 : : {
481 : 0 : Polygon& rPoly = aPolyPoly[ i ];
482 : :
483 : 0 : const sal_uInt16 nSize = rPoly.GetSize();
484 : 0 : if( nSize )
485 : : {
486 : : // convert polygon to flash EM_SQUARE (1024x1024)
487 : 0 : for( n = 0; n < nSize; n++ )
488 : : {
489 : 0 : Point aPoint( rPoly[n] );
490 : 0 : aPoint.X() = static_cast<long>((double(aPoint.X()) * 1024.0 ) / double(aOldFont.GetHeight()));
491 : 0 : aPoint.Y() = static_cast<long>((double(aPoint.Y()) * 1024.0 ) / double(aOldFont.GetHeight()));
492 : 0 : rPoly[n] = aPoint;
493 : : }
494 : 0 : Writer::Impl_addPolygon( maGlyphData, rPoly, true );
495 : : }
496 : : }
497 : 0 : Writer::Impl_addEndShapeRecord( maGlyphData );
498 : :
499 : 0 : maGlyphData.pad();
500 : :
501 : 0 : pVDev->SetFont( aOldFont );
502 : :
503 : 0 : return mnNextIndex++;
504 : : }
505 : :
506 : : // -----------------------------------------------------------------------------
507 : :
508 : 0 : void FlashFont::write( SvStream& out )
509 : : {
510 : 0 : Tag aTag( TAG_DEFINEFONT );
511 : :
512 : 0 : aTag.addUI16( mnId );
513 : :
514 : 0 : sal_uInt16 nGlyphs = _uInt16( maGlyphOffsets.size() );
515 : 0 : sal_uInt16 nOffset = nGlyphs * sizeof( sal_uInt16 );
516 : :
517 : 0 : for(vector< sal_uInt16 >::iterator i = maGlyphOffsets.begin(); i != maGlyphOffsets.end(); ++i)
518 : 0 : aTag.addUI16( nOffset + (*i) );
519 : :
520 : 0 : aTag.addBits( maGlyphData );
521 : :
522 : 0 : aTag.write( out );
523 : 0 : }
524 : :
525 : : ////////////////////////////////////////////////////////////////////////////////
526 : :
527 : : /** this c'tor creates a solid fill style */
528 : 0 : FillStyle::FillStyle( const Color& rSolidColor )
529 : : : meType( solid ),
530 : 0 : maColor( rSolidColor )
531 : : {
532 : 0 : }
533 : :
534 : : // -----------------------------------------------------------------------------
535 : :
536 : : /** this c'tor creates a tiled or clipped bitmap fill style */
537 : 0 : FillStyle::FillStyle( sal_uInt16 nBitmapId, bool bClipped, const ::basegfx::B2DHomMatrix& rMatrix ) // #i73264#
538 : : : meType( bClipped ? clipped_bitmap : tiled_bitmap ),
539 : : maMatrix( rMatrix ),
540 : 0 : mnBitmapId( nBitmapId )
541 : : {
542 : 0 : }
543 : :
544 : : // -----------------------------------------------------------------------------
545 : :
546 : 0 : FillStyle::FillStyleType Impl_getFillStyleType( const Gradient& rGradient )
547 : : {
548 : 0 : switch( rGradient.GetStyle() )
549 : : {
550 : : case GradientStyle_ELLIPTICAL:
551 : : case GradientStyle_RADIAL:
552 : 0 : return FillStyle::radial_gradient;
553 : : // case GradientStyle_AXIAL:
554 : : // case GradientStyle_SQUARE:
555 : : // case GradientStyle_RECT:
556 : : // case GradientStyle_LINEAR:
557 : : default:
558 : 0 : return FillStyle::linear_gradient;
559 : : }
560 : : }
561 : :
562 : : // -----------------------------------------------------------------------------
563 : :
564 : : /** this c'tor creates a linear or radial gradient fill style */
565 : 0 : FillStyle::FillStyle( const Rectangle& rBoundRect, const Gradient& rGradient )
566 : 0 : : meType( Impl_getFillStyleType( rGradient ) ),
567 : : maGradient( rGradient ),
568 : 0 : maBoundRect( rBoundRect )
569 : : {
570 : 0 : }
571 : :
572 : : // -----------------------------------------------------------------------------
573 : :
574 : 0 : void FillStyle::addTo( Tag* pTag ) const
575 : : {
576 : 0 : pTag->addUI8( sal::static_int_cast<sal_uInt8>( meType ) );
577 : 0 : switch( meType )
578 : : {
579 : : case solid:
580 : 0 : pTag->addRGBA( maColor );
581 : 0 : break;
582 : : case linear_gradient:
583 : : case radial_gradient:
584 : 0 : Impl_addGradient( pTag );
585 : 0 : break;
586 : : case tiled_bitmap:
587 : : case clipped_bitmap:
588 : 0 : pTag->addUI16( mnBitmapId );
589 : 0 : pTag->addMatrix( maMatrix );
590 : 0 : break;
591 : : }
592 : 0 : }
593 : :
594 : : // -----------------------------------------------------------------------------
595 : :
596 : : struct GradRecord
597 : : {
598 : : sal_uInt8 mnRatio;
599 : : Color maColor;
600 : :
601 : 0 : GradRecord( sal_uInt8 nRatio, const Color& rColor ) : mnRatio( nRatio ), maColor( rColor ) {}
602 : : };
603 : :
604 : : // TODO: better emulation of our gradients
605 : 0 : void FillStyle::Impl_addGradient( Tag* pTag ) const
606 : : {
607 : 0 : vector< struct GradRecord > aGradientRecords;
608 : 0 : basegfx::B2DHomMatrix m(basegfx::tools::createRotateB2DHomMatrix((maGradient.GetAngle() - 900) * F_PI1800));
609 : :
610 : 0 : switch( maGradient.GetStyle() )
611 : : {
612 : : case GradientStyle_ELLIPTICAL:
613 : : case GradientStyle_RADIAL:
614 : : {
615 : 0 : aGradientRecords.push_back( GradRecord( 0x00, maGradient.GetEndColor() ) );
616 : 0 : aGradientRecords.push_back( GradRecord( 0xff, maGradient.GetStartColor() ) );
617 : :
618 : 0 : double tx = ( maGradient.GetOfsX() * 32768.0 ) / 100.0;
619 : 0 : double ty = ( maGradient.GetOfsY() * 32768.0 ) / 100.0;
620 : 0 : double scalex = (double)maBoundRect.GetWidth() / 32768.0;
621 : 0 : double scaley = (double)maBoundRect.GetHeight() / 32768.0;
622 : :
623 : 0 : m.scale( 1.2, 1.2 );
624 : :
625 : 0 : if( scalex > scaley )
626 : : {
627 : 0 : double scale_move = scaley / scalex;
628 : :
629 : 0 : m.translate( tx, scale_move * ty );
630 : :
631 : :
632 : 0 : m.scale( scalex, scalex );
633 : : }
634 : : else
635 : : {
636 : 0 : double scale_move = scalex / scaley;
637 : :
638 : 0 : m.translate( scale_move * tx, ty );
639 : :
640 : :
641 : 0 : m.scale( scaley, scaley );
642 : : }
643 : :
644 : : }
645 : 0 : break;
646 : : case GradientStyle_AXIAL:
647 : : {
648 : 0 : aGradientRecords.push_back( GradRecord( 0x00, maGradient.GetEndColor() ) );
649 : 0 : aGradientRecords.push_back( GradRecord( 0x80, maGradient.GetStartColor() ) );
650 : 0 : aGradientRecords.push_back( GradRecord( 0xff, maGradient.GetEndColor() ) );
651 : 0 : double tx = ( 32768.0 / 2.0 );
652 : 0 : double ty = ( 32768.0 / 2.0 );
653 : 0 : double scalex = (double)maBoundRect.GetWidth() / 32768.0;
654 : 0 : double scaley = (double)maBoundRect.GetHeight() / 32768.0;
655 : :
656 : 0 : m.translate( tx, ty );
657 : 0 : m.scale( scalex, scaley );
658 : : }
659 : 0 : break;
660 : : case GradientStyle_SQUARE:
661 : : case GradientStyle_RECT:
662 : : case GradientStyle_LINEAR:
663 : : {
664 : 0 : aGradientRecords.push_back( GradRecord( 0x00, maGradient.GetStartColor() ) );
665 : 0 : aGradientRecords.push_back( GradRecord( 0xff, maGradient.GetEndColor() ) );
666 : 0 : double scalex = (double)maBoundRect.GetWidth() / 32768.0;
667 : 0 : double scaley = (double)maBoundRect.GetHeight() / 32768.0;
668 : :
669 : 0 : m.scale( scalex, scaley );
670 : :
671 : 0 : m.translate( maBoundRect.GetWidth() / 2.0, maBoundRect.GetHeight() / 2.0 );
672 : : }
673 : 0 : break;
674 : 0 : case GradientStyle_FORCE_EQUAL_SIZE: break;
675 : : }
676 : :
677 : 0 : m.translate( maBoundRect.nLeft, maBoundRect.nTop );
678 : :
679 : 0 : pTag->addMatrix( m );
680 : :
681 : : DBG_ASSERT( aGradientRecords.size() < 8, "Illegal FlashGradient!" );
682 : :
683 : 0 : pTag->addUI8( static_cast<sal_uInt8>( aGradientRecords.size() ) );
684 : :
685 : 0 : for(std::vector< GradRecord >::iterator i = aGradientRecords.begin(); i != aGradientRecords.end(); ++i)
686 : : {
687 : 0 : pTag->addUI8( (*i).mnRatio );
688 : 0 : pTag->addRGBA( (*i).maColor );
689 : 0 : }
690 : 0 : }
691 : :
692 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|