LibreOffice Module vcl (master)  1
emfwr.cxx
Go to the documentation of this file.
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 <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include <algorithm>
24 
25 #include "emfwr.hxx"
26 #include <tools/helpers.hxx>
27 #include <tools/fract.hxx>
28 #include <tools/stream.hxx>
31 #include <vcl/lineinfo.hxx>
32 #include <vcl/dibtools.hxx>
33 #include <vcl/metaact.hxx>
34 #include <memory>
35 
36 #define WIN_EMR_POLYGON 3
37 #define WIN_EMR_POLYLINE 4
38 #define WIN_EMR_POLYBEZIERTO 5
39 #define WIN_EMR_POLYLINETO 6
40 #define WIN_EMR_POLYPOLYGON 8
41 #define WIN_EMR_SETWINDOWEXTEX 9
42 #define WIN_EMR_SETWINDOWORGEX 10
43 #define WIN_EMR_SETVIEWPORTEXTEX 11
44 #define WIN_EMR_SETVIEWPORTORGEX 12
45 #define WIN_EMR_EOF 14
46 #define WIN_EMR_SETPIXELV 15
47 #define WIN_EMR_SETMAPMODE 17
48 #define WIN_EMR_SETBKMODE 18
49 #define WIN_EMR_SETROP2 20
50 #define WIN_EMR_SETTEXTALIGN 22
51 #define WIN_EMR_SETTEXTCOLOR 24
52 #define WIN_EMR_MOVETOEX 27
53 #define WIN_EMR_INTERSECTCLIPRECT 30
54 #define WIN_EMR_SAVEDC 33
55 #define WIN_EMR_RESTOREDC 34
56 #define WIN_EMR_SELECTOBJECT 37
57 #define WIN_EMR_CREATEPEN 38
58 #define WIN_EMR_CREATEBRUSHINDIRECT 39
59 #define WIN_EMR_DELETEOBJECT 40
60 #define WIN_EMR_ELLIPSE 42
61 #define WIN_EMR_RECTANGLE 43
62 #define WIN_EMR_ROUNDRECT 44
63 #define WIN_EMR_LINETO 54
64 #define WIN_EMR_BEGINPATH 59
65 #define WIN_EMR_ENDPATH 60
66 #define WIN_EMR_CLOSEFIGURE 61
67 #define WIN_EMR_FILLPATH 62
68 #define WIN_EMR_STROKEPATH 64
69 
70 #define WIN_EMR_GDICOMMENT 70
71 #define WIN_EMR_STRETCHDIBITS 81
72 #define WIN_EMR_EXTCREATEFONTINDIRECTW 82
73 #define WIN_EMR_EXTTEXTOUTW 84
74 
75 #define WIN_SRCCOPY 0x00CC0020L
76 #define WIN_SRCPAINT 0x00EE0086L
77 #define WIN_SRCAND 0x008800C6L
78 #define WIN_SRCINVERT 0x00660046L
79 #define WIN_EMR_COMMENT_EMFPLUS 0x2B464D45L
80 
81 #define HANDLE_INVALID 0xffffffff
82 #define MAXHANDLES 65000
83 
84 #define LINE_SELECT 0x00000001
85 #define FILL_SELECT 0x00000002
86 #define TEXT_SELECT 0x00000004
87 
88 /* Text Alignment Options */
89 #define TA_RIGHT 2
90 
91 #define TA_TOP 0
92 #define TA_BOTTOM 8
93 #define TA_BASELINE 24
94 #define TA_RTLREADING 256
95 
96 #define MM_ANISOTROPIC 8
97 
99 {
100  Header = 0x4001,
101  EndOfFile = 0x4002,
102  GetDC = 0x4004,
103  FillPolygon = 0x400C,
104  SetAntiAliasMode = 0x401E,
105  SetInterpolationMode = 0x4021,
106  SetPixelOffsetMode = 0x4022,
107  SetCompositingQuality = 0x4024
108 };
109 
110 void EMFWriter::ImplBeginCommentRecord( sal_Int32 nCommentType )
111 {
113  m_rStm.SeekRel( 4 );
114  m_rStm.WriteInt32( nCommentType );
115 }
116 
118 {
119  if( mbRecordOpen )
120  {
121  sal_Int32 nActPos = m_rStm.Tell();
122  m_rStm.Seek( mnRecordPos + 8 );
123  m_rStm.WriteUInt32( nActPos - mnRecordPos - 0xc );
124  m_rStm.Seek( nActPos );
125  }
126  ImplEndRecord();
127 }
128 
129 void EMFWriter::ImplBeginPlusRecord( EmfPlusRecordType nType, sal_uInt16 nFlags )
130 {
131  SAL_WARN_IF( mbRecordPlusOpen, "vcl", "Another EMF+ record is already opened!" );
132 
133  if( !mbRecordPlusOpen )
134  {
135  mbRecordPlusOpen = true;
137 
138  m_rStm.WriteUInt16( static_cast<sal_uInt16>(nType) ).WriteUInt16( nFlags );
139  m_rStm.SeekRel( 8 );
140  }
141 }
142 
144 {
145  SAL_WARN_IF( !mbRecordPlusOpen, "vcl", "EMF+ Record was not opened!" );
146 
147  if( mbRecordPlusOpen )
148  {
149  sal_Int32 nActPos = m_rStm.Tell();
150  sal_Int32 nSize = nActPos - mnRecordPlusPos;
151  m_rStm.Seek( mnRecordPlusPos + 4 );
152  m_rStm.WriteUInt32( nSize ) // Size
153  .WriteUInt32( nSize - 0xc ); // Data Size
154  m_rStm.Seek( nActPos );
155  mbRecordPlusOpen = false;
156  }
157 }
158 
159 void EMFWriter::ImplPlusRecord( EmfPlusRecordType nType, sal_uInt16 nFlags )
160 {
161  ImplBeginPlusRecord( nType, nFlags );
163 }
164 
165 void EMFWriter::WriteEMFPlusHeader( const Size &rMtfSizePix, const Size &rMtfSizeLog )
166 {
168 
169  sal_Int32 nDPIX = rMtfSizePix.Width()*25;
170  sal_Int32 nDivX = rMtfSizeLog.Width()/100;
171  if (nDivX)
172  nDPIX /= nDivX; // DPI X
173 
174  sal_Int32 nDPIY = rMtfSizePix.Height()*25;
175  sal_Int32 nDivY = rMtfSizeLog.Height()/100;
176  if (nDivY)
177  nDPIY /= nDivY; // DPI Y
178 
180  m_rStm.WriteInt16( 0x01 ) // Flags - Dual Mode // TODO: Check this
181  .WriteInt32( 0x1C ) // Size
182  .WriteInt32( 0x10 ) // Data Size
183  .WriteInt32( 0xdbc01002 ) // (lower 12bits) 1-> v1 2-> v1.1 // TODO: Check this
184  .WriteInt32( 0x01 ) // Video display
185  .WriteInt32( nDPIX )
186  .WriteInt32( nDPIY );
188 
189  // Write more properties
192  ImplPlusRecord( EmfPlusRecordType::SetAntiAliasMode, 0x09 ); // TODO: Check actual values for AntiAlias
193  ImplPlusRecord( EmfPlusRecordType::SetCompositingQuality, 0x0100 ); // Default Quality
197 }
198 
200 {
204 }
205 
206 void EMFWriter::ImplWritePlusColor( const Color& rColor, sal_uInt32 nTrans )
207 {
208  sal_uInt32 nAlpha = ((100-nTrans)*0xFF)/100;
209  sal_uInt32 nCol = rColor.GetBlue();
210 
211  nCol |= static_cast<sal_uInt32>(rColor.GetGreen()) << 8;
212  nCol |= static_cast<sal_uInt32>(rColor.GetRed()) << 16;
213  nCol |= ( nAlpha << 24 );
214  m_rStm.WriteUInt32( nCol );
215 }
216 
218 {
219  // Convert to pixels
220  const Point aPoint(maVDev->LogicToPixel( rPoint, maDestMapMode ));
221  m_rStm.WriteUInt16( aPoint.X() ).WriteUInt16( aPoint.Y() );
222 }
223 
224 void EMFWriter::ImplWritePlusFillPolygonRecord( const tools::Polygon& rPoly, sal_uInt32 nTrans )
225 {
227  if( rPoly.GetSize() )
228  {
229  ImplBeginPlusRecord( EmfPlusRecordType::FillPolygon, 0xC000 ); // Sets the color as well
230  ImplWritePlusColor( maVDev->GetFillColor(), nTrans );
231  m_rStm.WriteUInt32( rPoly.GetSize() );
232  for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ )
233  ImplWritePlusPoint( rPoly[ i ] );
235  }
237 }
238 
240 {
241  const sal_uLong nHeaderPos = m_rStm.Tell();
242 
243  maVDev->EnableOutput( false );
244  maVDev->SetMapMode( rMtf.GetPrefMapMode() );
245  // don't work with pixel as destination map mode -> higher resolution preferable
246  maDestMapMode.SetMapUnit( MapUnit::Map100thMM );
247  mHandlesUsed = std::vector<bool>(MAXHANDLES, false);
249  mbRecordOpen = mbRecordPlusOpen = false;
252  mnHorTextAlign = 0;
253 
254  const Size aMtfSizePix( maVDev->LogicToPixel( rMtf.GetPrefSize(), rMtf.GetPrefMapMode() ) );
255  const Size aMtfSizeLog( OutputDevice::LogicToLogic(rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
256 
257  // seek over header
258  // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits()
259  m_rStm.SeekRel( 108 );
260 
261  // Write EMF+ Header
262  WriteEMFPlusHeader( aMtfSizePix, aMtfSizeLog );
263 
264  // write initial values
265 
266  // set 100th mm map mode in EMF
269  ImplEndRecord();
270 
272  m_rStm.WriteInt32( maVDev->GetDPIX() ).WriteInt32( maVDev->GetDPIY() );
273  ImplEndRecord();
274 
276  m_rStm.WriteInt32( 2540 ).WriteInt32( 2540 );
277  ImplEndRecord();
278 
280  m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
281  ImplEndRecord();
282 
284  m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
285  ImplEndRecord();
286 
288 
290  m_rStm.WriteUInt32( 1 ); // TRANSPARENT
291  ImplEndRecord();
292 
293  // write emf data
294  ImplWrite( rMtf );
295 
297 
299  m_rStm.WriteUInt32( 0 ) // nPalEntries
300  .WriteUInt32( 0x10 ) // offPalEntries
301  .WriteUInt32( 0x14 ); // nSizeLast
302  ImplEndRecord();
303 
304  // write header
305  const sal_uLong nEndPos = m_rStm.Tell(); m_rStm.Seek( nHeaderPos );
306 
307  m_rStm.WriteUInt32( 0x00000001 ).WriteUInt32( 108 ) //use [MS-EMF 2.2.11] HeaderExtension2 Object
308  .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizePix.Width() - 1 ).WriteInt32( aMtfSizePix.Height() - 1 )
309  .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizeLog.Width() - 1 ).WriteInt32( aMtfSizeLog.Height() - 1 )
310  .WriteUInt32( 0x464d4520 ).WriteUInt32( 0x10000 ).WriteUInt32( nEndPos - nHeaderPos )
311  .WriteUInt32( mnRecordCount ).WriteUInt16( mnHandleCount + 1 ).WriteUInt16( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
312  .WriteInt32( aMtfSizePix.Width() ).WriteInt32( aMtfSizePix.Height() )
313  .WriteInt32( aMtfSizeLog.Width() / 100 ).WriteInt32( aMtfSizeLog.Height() / 100 )
314  .WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
315  .WriteInt32( aMtfSizeLog.Width() * 10 ).WriteInt32( aMtfSizeLog.Height() * 10 ); //use [MS-EMF 2.2.11] HeaderExtension2 Object
316 
317  m_rStm.Seek( nEndPos );
318  mHandlesUsed.clear();
319 
320  return( m_rStm.GetError() == ERRCODE_NONE );
321 }
322 
324 {
325  sal_uLong nHandle = HANDLE_INVALID;
326 
327  for( sal_uLong i = 0; i < mHandlesUsed.size() && ( HANDLE_INVALID == nHandle ); i++ )
328  {
329  if( !mHandlesUsed[ i ] )
330  {
331  mHandlesUsed[ i ] = true;
332 
333  if( ( nHandle = i ) == mnHandleCount )
334  mnHandleCount++;
335  }
336  }
337 
338  SAL_WARN_IF( nHandle == HANDLE_INVALID, "vcl", "No more handles available" );
339  return( nHandle != HANDLE_INVALID ? nHandle + 1 : HANDLE_INVALID );
340 }
341 
343 {
344  SAL_WARN_IF( !nHandle || ( nHandle >= mHandlesUsed.size() ), "vcl", "Handle out of range" );
345  mHandlesUsed[ nHandle - 1 ] = false;
346 }
347 
348 void EMFWriter::ImplBeginRecord( sal_uInt32 nType )
349 {
350  SAL_WARN_IF( mbRecordOpen, "vcl", "Another record is already opened!" );
351 
352  if( !mbRecordOpen )
353  {
354  mbRecordOpen = true;
355  mnRecordPos = m_rStm.Tell();
356 
357  m_rStm.WriteUInt32( nType );
358  m_rStm.SeekRel( 4 );
359  }
360 }
361 
363 {
364  SAL_WARN_IF( !mbRecordOpen, "vcl", "Record was not opened!" );
365 
366  if( !mbRecordOpen )
367  return;
368 
369  sal_Int32 nFillBytes, nActPos = m_rStm.Tell();
370  m_rStm.Seek( mnRecordPos + 4 );
371  nFillBytes = nActPos - mnRecordPos;
372  nFillBytes += 3; // each record has to be dword aligned
373  nFillBytes ^= 3;
374  nFillBytes &= 3;
375  m_rStm.WriteUInt32( ( nActPos - mnRecordPos ) + nFillBytes );
376  m_rStm.Seek( nActPos );
377  while( nFillBytes-- )
378  m_rStm.WriteUChar( 0 );
379  mnRecordCount++;
380  mbRecordOpen = false;
381 
382 }
383 
384 bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32& rHandle, sal_uLong nSelectType )
385 {
386  if( rHandle != HANDLE_INVALID )
387  {
388  sal_uInt32 nStockObject = 0x80000000;
389 
390  if( LINE_SELECT == nSelectType )
391  nStockObject |= 0x00000007;
392  else if( FILL_SELECT == nSelectType )
393  nStockObject |= 0x00000001;
394  else if( TEXT_SELECT == nSelectType )
395  nStockObject |= 0x0000000a;
396 
397  // select stock object first
399  m_rStm.WriteUInt32( nStockObject );
400  ImplEndRecord();
401 
402  // destroy handle of created object
404  m_rStm.WriteUInt32( rHandle );
405  ImplEndRecord();
406 
407  // mark handle as free
408  ImplReleaseHandle( rHandle );
409  }
410 
411  rHandle = ImplAcquireHandle();
412 
413  return( HANDLE_INVALID != rHandle );
414 }
415 
417 {
419  {
420  sal_uInt32 nStyle = maVDev->IsLineColor() ? 0 : 5;
421 
423  m_rStm.WriteUInt32( mnLineHandle ).WriteUInt32( nStyle ).WriteUInt32( 0/*nWidth*/ ).WriteUInt32( 0/*nHeight*/ );
424  ImplWriteColor( maVDev->GetLineColor() );
425  ImplEndRecord();
426 
429  ImplEndRecord();
430  }
431 }
432 
434 {
436  {
437  sal_uInt32 nStyle = maVDev->IsFillColor() ? 0 : 1;
438 
441  ImplWriteColor( maVDev->GetFillColor() );
442  m_rStm.WriteUInt32( 0/*nPatternStyle*/ );
443  ImplEndRecord();
444 
447  ImplEndRecord();
448  }
449 }
450 
452 {
454  return;
455 
456  const vcl::Font& rFont = maVDev->GetFont();
457  const OUString& aFontName( rFont.GetFamilyName() );
458  sal_Int32 nWeight;
459  sal_uInt16 i;
460  sal_uInt8 nPitchAndFamily;
461 
464  ImplWriteExtent( -rFont.GetFontSize().Height() );
465  ImplWriteExtent( rFont.GetFontSize().Width() );
466  m_rStm.WriteInt32( rFont.GetOrientation() ).WriteInt32( rFont.GetOrientation() );
467 
468  switch( rFont.GetWeight() )
469  {
470  case WEIGHT_THIN: nWeight = 100; break;
471  case WEIGHT_ULTRALIGHT: nWeight = 200; break;
472  case WEIGHT_LIGHT: nWeight = 300; break;
473  case WEIGHT_SEMILIGHT: nWeight = 300; break;
474  case WEIGHT_NORMAL: nWeight = 400; break;
475  case WEIGHT_MEDIUM: nWeight = 500; break;
476  case WEIGHT_SEMIBOLD: nWeight = 600; break;
477  case WEIGHT_BOLD: nWeight = 700; break;
478  case WEIGHT_ULTRABOLD: nWeight = 800; break;
479  case WEIGHT_BLACK: nWeight = 900; break;
480  default: nWeight = 0; break;
481  }
482 
483  m_rStm.WriteInt32( nWeight );
484  m_rStm.WriteUChar( ( ITALIC_NONE == rFont.GetItalic() ) ? 0 : 1 );
485  m_rStm.WriteUChar( ( LINESTYLE_NONE == rFont.GetUnderline() ) ? 0 : 1 );
486  m_rStm.WriteUChar( ( STRIKEOUT_NONE == rFont.GetStrikeout() ) ? 0 : 1 );
487  m_rStm.WriteUChar( ( RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet() ) ? 2 : 0 );
488  m_rStm.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
489 
490  switch( rFont.GetPitch() )
491  {
492  case PITCH_FIXED: nPitchAndFamily = 0x01; break;
493  case PITCH_VARIABLE: nPitchAndFamily = 0x02; break;
494  default: nPitchAndFamily = 0x00; break;
495  }
496 
497  switch( rFont.GetFamilyType() )
498  {
499  case FAMILY_DECORATIVE: nPitchAndFamily |= 0x50; break;
500  case FAMILY_MODERN: nPitchAndFamily |= 0x30; break;
501  case FAMILY_ROMAN: nPitchAndFamily |= 0x10; break;
502  case FAMILY_SCRIPT: nPitchAndFamily |= 0x40; break;
503  case FAMILY_SWISS: nPitchAndFamily |= 0x20; break;
504  default: break;
505  }
506 
507  m_rStm.WriteUChar( nPitchAndFamily );
508 
509  for( i = 0; i < 32; i++ )
510  m_rStm.WriteUInt16( ( i < aFontName.getLength() ) ? aFontName[ i ] : 0 );
511 
512  // dummy elfFullName
513  for( i = 0; i < 64; i++ )
514  m_rStm.WriteUInt16( 0 );
515 
516  // dummy elfStyle
517  for( i = 0; i < 32; i++ )
518  m_rStm.WriteUInt16( 0 );
519 
520  // dummy elfVersion, elfStyleSize, elfMatch, elfReserved
522 
523  // dummy elfVendorId
524  m_rStm.WriteUInt32( 0 );
525 
526  // dummy elfCulture
527  m_rStm.WriteUInt32( 0 );
528 
529  // dummy elfPanose
531 
532  // fill record to get a record size divideable by 4
533  m_rStm.WriteUInt16( 0 );
534 
535  ImplEndRecord();
536 
537  // TextAlign
538  sal_uInt32 nTextAlign;
539 
540  switch( rFont.GetAlignment() )
541  {
542  case ALIGN_TOP: nTextAlign = TA_TOP; break;
543  case ALIGN_BOTTOM: nTextAlign = TA_BOTTOM; break;
544  default: nTextAlign = TA_BASELINE; break;
545  }
546  nTextAlign |= mnHorTextAlign;
547 
549  m_rStm.WriteUInt32( nTextAlign );
550  ImplEndRecord();
551 
552  // Text color
554  ImplWriteColor( maVDev->GetTextColor() );
555  ImplEndRecord();
556 
559  ImplEndRecord();
560 
561 }
562 
563 void EMFWriter::ImplWriteColor( const Color& rColor )
564 {
565  sal_uInt32 nCol = rColor.GetRed();
566 
567  nCol |= static_cast<sal_uInt32>(rColor.GetGreen()) << 8;
568  nCol |= static_cast<sal_uInt32>(rColor.GetBlue()) << 16;
569 
570  m_rStm.WriteUInt32( nCol );
571 }
572 
574 {
575  sal_uInt32 nROP2;
576 
577  switch( eRop )
578  {
579  case RasterOp::Invert: nROP2 = 6; break;
580  case RasterOp::Xor: nROP2 = 7; break;
581  default: nROP2 = 13;break;
582  }
583 
585  m_rStm.WriteUInt32( nROP2 );
586  ImplEndRecord();
587 }
588 
589 void EMFWriter::ImplWriteExtent( long nExtent )
590 {
591  nExtent = OutputDevice::LogicToLogic( Size( nExtent, 0 ), maVDev->GetMapMode(), maDestMapMode ).Width();
592  m_rStm.WriteInt32( nExtent );
593 }
594 
595 void EMFWriter::ImplWritePoint( const Point& rPoint )
596 {
597  const Point aPoint( OutputDevice::LogicToLogic( rPoint, maVDev->GetMapMode(), maDestMapMode ));
598  m_rStm.WriteInt32( aPoint.X() ).WriteInt32( aPoint.Y() );
599 }
600 
601 void EMFWriter::ImplWriteSize( const Size& rSize)
602 {
603  const Size aSize( OutputDevice::LogicToLogic( rSize, maVDev->GetMapMode(), maDestMapMode ));
604  m_rStm.WriteInt32( aSize.Width() ).WriteInt32( aSize.Height() );
605 }
606 
608 {
609  const tools::Rectangle aRect( OutputDevice::LogicToLogic ( rRect, maVDev->GetMapMode(), maDestMapMode ));
610  auto right = aRect.IsWidthEmpty() ? aRect.Left() : aRect.Right();
611  auto bottom = aRect.IsHeightEmpty() ? aRect.Top() : aRect.Bottom();
612  m_rStm
613  .WriteInt32( aRect.Left() )
614  .WriteInt32( aRect.Top() )
615  .WriteInt32( right )
616  .WriteInt32( bottom );
617 }
618 
619 void EMFWriter::ImplWritePolygonRecord( const tools::Polygon& rPoly, bool bClose )
620 {
621  if( rPoly.GetSize() )
622  {
623  if( rPoly.HasFlags() )
624  ImplWritePath( rPoly, bClose );
625  else
626  {
627  if( bClose )
629 
631 
633  ImplWriteRect( rPoly.GetBoundRect() );
634  m_rStm.WriteUInt32( rPoly.GetSize() );
635 
636  for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ )
637  ImplWritePoint( rPoly[ i ] );
638 
639  ImplEndRecord();
640  }
641  }
642 }
643 
645 {
646  sal_uInt16 n, i, nPolyCount = rPolyPoly.Count();
647 
648  if( nPolyCount )
649  {
650  if( 1 == nPolyCount )
651  ImplWritePolygonRecord( rPolyPoly[ 0 ], true );
652  else
653  {
654  bool bHasFlags = false;
655  sal_uInt32 nTotalPoints = 0;
656 
657  for( i = 0; i < nPolyCount; i++ )
658  {
659  nTotalPoints += rPolyPoly[ i ].GetSize();
660  if ( rPolyPoly[ i ].HasFlags() )
661  bHasFlags = true;
662  }
663  if( nTotalPoints )
664  {
665  if ( bHasFlags )
666  ImplWritePath( rPolyPoly, true );
667  else
668  {
671 
673  ImplWriteRect( rPolyPoly.GetBoundRect() );
674  m_rStm.WriteUInt32( nPolyCount ).WriteUInt32( nTotalPoints );
675 
676  for( i = 0; i < nPolyCount; i++ )
677  m_rStm.WriteUInt32( rPolyPoly[ i ].GetSize() );
678 
679  for( i = 0; i < nPolyCount; i++ )
680  {
681  const tools::Polygon& rPoly = rPolyPoly[ i ];
682 
683  for( n = 0; n < rPoly.GetSize(); n++ )
684  ImplWritePoint( rPoly[ n ] );
685  }
686  ImplEndRecord();
687  }
688  }
689  }
690  }
691 }
692 
693 void EMFWriter::ImplWritePath( const tools::PolyPolygon& rPolyPoly, bool bClosed )
694 {
695  if ( bClosed )
698 
700  ImplEndRecord();
701 
702  sal_uInt16 i, n, o, nPolyCount = rPolyPoly.Count();
703  for ( i = 0; i < nPolyCount; i++ )
704  {
705  n = 0;
706  const tools::Polygon& rPoly = rPolyPoly[ i ];
707  while ( n < rPoly.GetSize() )
708  {
709  if( n == 0 )
710  {
712  ImplWritePoint( rPoly[ 0 ] );
713  ImplEndRecord();
714  n++;
715  continue;
716  }
717 
718  sal_uInt16 nBezPoints = 0;
719 
720  while ( ( ( nBezPoints + n + 2 ) < rPoly.GetSize() ) && ( rPoly.GetFlags( nBezPoints + n ) == PolyFlags::Control ) )
721  nBezPoints += 3;
722 
723  if ( nBezPoints )
724  {
726  tools::Polygon aNewPoly( nBezPoints + 1 );
727  aNewPoly[ 0 ] = rPoly[ n - 1 ];
728  for ( o = 0; o < nBezPoints; o++ )
729  aNewPoly[ o + 1 ] = rPoly[ n + o ];
730  ImplWriteRect( aNewPoly.GetBoundRect() );
731  m_rStm.WriteUInt32( nBezPoints );
732  for( o = 1; o < aNewPoly.GetSize(); o++ )
733  ImplWritePoint( aNewPoly[ o ] );
734  ImplEndRecord();
735  n = n + nBezPoints;
736  }
737  else
738  {
739  sal_uInt16 nPoints = 1;
740  while( ( nPoints + n ) < rPoly.GetSize() && ( rPoly.GetFlags( nPoints + n ) != PolyFlags::Control ) )
741  nPoints++;
742 
743  if ( nPoints > 1 )
744  {
746  tools::Polygon aNewPoly( nPoints + 1 );
747  aNewPoly[ 0 ] = rPoly[ n - 1];
748  for ( o = 1; o <= nPoints; o++ )
749  aNewPoly[ o ] = rPoly[ n - 1 + o ];
750  ImplWriteRect( aNewPoly.GetBoundRect() );
751  m_rStm.WriteUInt32( nPoints );
752  for( o = 1; o < aNewPoly.GetSize(); o++ )
753  ImplWritePoint( aNewPoly[ o ] );
754  ImplEndRecord();
755  }
756  else
757  {
759  ImplWritePoint( rPoly[ n ] );
760  ImplEndRecord();
761  }
762  n = n + nPoints;
763  }
764  if ( bClosed && ( n == rPoly.GetSize() ) )
765  {
767  ImplEndRecord();
768  }
769  }
770  }
772  ImplEndRecord();
774  ImplWriteRect( rPolyPoly.GetBoundRect() );
775  ImplEndRecord();
776 }
777 
778 void EMFWriter::ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt,
779  const Size& rSz, sal_uInt32 nROP )
780 {
781  if( !rBmp )
782  return;
783 
784  SvMemoryStream aMemStm( 65535, 65535 );
785  const Size aBmpSizePixel( rBmp.GetSizePixel() );
786 
788  ImplWriteRect( tools::Rectangle( rPt, rSz ) );
789  ImplWritePoint( rPt );
790  m_rStm.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aBmpSizePixel.Width() ).WriteInt32( aBmpSizePixel.Height() );
791 
792  // write offset positions and sizes later
793  const sal_uLong nOffPos = m_rStm.Tell();
794  m_rStm.SeekRel( 16 );
795 
796  m_rStm.WriteUInt32( 0 ).WriteInt32( ( RasterOp::Xor == maVDev->GetRasterOp() && WIN_SRCCOPY == nROP ) ? WIN_SRCINVERT : nROP );
797  ImplWriteSize( rSz );
798 
799  WriteDIB(rBmp, aMemStm, true, false);
800 
801  sal_uInt32 nDIBSize = aMemStm.Tell(), nHeaderSize, nCompression, nColsUsed, nPalCount, nImageSize;
802  sal_uInt16 nBitCount;
803 
804  // get DIB parameters
805  aMemStm.Seek( 0 );
806  aMemStm.ReadUInt32( nHeaderSize );
807  aMemStm.SeekRel( 10 );
808  aMemStm.ReadUInt16( nBitCount ).ReadUInt32( nCompression ).ReadUInt32( nImageSize );
809  aMemStm.SeekRel( 8 );
810  aMemStm.ReadUInt32( nColsUsed );
811 
812  if (nBitCount <= 8)
813  {
814  if (nColsUsed)
815  nPalCount = nColsUsed;
816  else
817  nPalCount = 1 << static_cast<sal_uInt32>(nBitCount);
818  }
819  else
820  {
821  if (nCompression == BITFIELDS)
822  nPalCount = 3;
823  else
824  nPalCount = 0;
825  }
826 
827  sal_uInt32 nPalSize = nPalCount * 4;
828 
829  m_rStm.WriteBytes( aMemStm.GetData(), nDIBSize );
830 
831  const sal_uLong nEndPos = m_rStm.Tell();
832  m_rStm.Seek( nOffPos );
833  m_rStm.WriteUInt32( 80 ).WriteUInt32( nHeaderSize + nPalSize );
834  m_rStm.WriteUInt32( 80 + nHeaderSize + nPalSize ).WriteUInt32( nImageSize );
835  m_rStm.Seek( nEndPos );
836 
837  ImplEndRecord();
838 
839 }
840 
841 void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, const long* pDXArray, sal_uInt32 nWidth )
842 {
843  sal_Int32 nLen = rText.getLength(), i;
844 
845  if( !nLen )
846  return;
847 
848  sal_uInt32 nNormWidth;
849  std::unique_ptr<long[]> pOwnArray;
850  long* pDX;
851 
852  // get text sizes
853  if( pDXArray )
854  {
855  nNormWidth = maVDev->GetTextWidth( rText );
856  pDX = const_cast<long*>(pDXArray);
857  }
858  else
859  {
860  pOwnArray.reset(new long[ nLen ]);
861  nNormWidth = maVDev->GetTextArray( rText, pOwnArray.get() );
862  pDX = pOwnArray.get();
863  }
864 
865  if( nLen > 1 )
866  {
867  nNormWidth = pDX[ nLen - 2 ] + maVDev->GetTextWidth( OUString(rText[ nLen - 1 ]) );
868 
869  if( nWidth && nNormWidth && ( nWidth != nNormWidth ) )
870  {
871  const double fFactor = static_cast<double>(nWidth) / nNormWidth;
872 
873  for( i = 0; i < ( nLen - 1 ); i++ )
874  pDX[ i ] = FRound( pDX[ i ] * fFactor );
875  }
876  }
877 
878  // write text record
880 
881  ImplWriteRect( tools::Rectangle( rPos, Size( nNormWidth, maVDev->GetTextHeight() ) ) );
882  m_rStm.WriteUInt32( 1 );
883  m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
884  ImplWritePoint( rPos );
885  m_rStm.WriteUInt32( nLen ).WriteUInt32( 76 ).WriteUInt32( 2 );
886  m_rStm.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 );
887  m_rStm.WriteUInt32( 76 + ( nLen << 1 ) + ( (nLen & 1 ) ? 2 : 0 ) );
888 
889  // write text
890  for( i = 0; i < nLen; i++ )
891  m_rStm.WriteUInt16( rText[ i ] );
892 
893  // padding word
894  if( nLen & 1 )
895  m_rStm.WriteUInt16( 0 );
896 
897  // write DX array
898  ImplWriteExtent( pDX[ 0 ] );
899 
900  if( nLen > 1 )
901  {
902  for( i = 1; i < ( nLen - 1 ); i++ )
903  ImplWriteExtent( pDX[ i ] - pDX[ i - 1 ] );
904 
905  ImplWriteExtent( pDX[ nLen - 2 ] / ( nLen - 1 ) );
906  }
907 
908  ImplEndRecord();
909 
910 }
911 
913 {
914  if(rLinePolygon.count())
915  {
916  basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
917  basegfx::B2DPolyPolygon aFillPolyPolygon;
918 
919  rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
920 
921  if(aLinePolyPolygon.count())
922  {
923  for(auto const& rB2DPolygon : aLinePolyPolygon)
924  {
925  ImplWritePolygonRecord( tools::Polygon(rB2DPolygon), false );
926  }
927  }
928 
929  if(aFillPolyPolygon.count())
930  {
931  const Color aOldLineColor(maVDev->GetLineColor());
932  const Color aOldFillColor(maVDev->GetFillColor());
933 
934  maVDev->SetLineColor();
935  maVDev->SetFillColor(aOldLineColor);
936 
937  for(auto const& rB2DPolygon : aFillPolyPolygon)
938  {
940  }
941 
942  maVDev->SetLineColor(aOldLineColor);
943  maVDev->SetFillColor(aOldFillColor);
944  }
945  }
946 }
947 
949 {
950  for( size_t j = 0, nActionCount = rMtf.GetActionSize(); j < nActionCount; j++ )
951  {
952  const MetaAction* pAction = rMtf.GetAction( j );
953  const MetaActionType nType = pAction->GetType();
954 
955  switch( nType )
956  {
958  {
959  const MetaPixelAction* pA = static_cast<const MetaPixelAction*>(pAction);
960 
963  ImplWritePoint( pA->GetPoint() );
964  ImplWriteColor( pA->GetColor() );
965  ImplEndRecord();
966  }
967  break;
968 
970  {
971  if( maVDev->IsLineColor() )
972  {
973  const MetaPointAction* pA = static_cast<const MetaPointAction*>(pAction);
974 
977  ImplWritePoint( pA->GetPoint() );
978  ImplWriteColor( maVDev->GetLineColor() );
979  ImplEndRecord();
980  }
981  }
982  break;
983 
985  {
986  if( maVDev->IsLineColor() )
987  {
988  const MetaLineAction* pA = static_cast<const MetaLineAction*>(pAction);
989 
990  if(pA->GetLineInfo().IsDefault())
991  {
993 
995  ImplWritePoint( pA->GetStartPoint() );
996  ImplEndRecord();
997 
999  ImplWritePoint( pA->GetEndPoint() );
1000  ImplEndRecord();
1001 
1003  ImplWritePoint( pA->GetEndPoint() );
1004  ImplWriteColor( maVDev->GetLineColor() );
1005  ImplEndRecord();
1006  }
1007  else
1008  {
1009  // LineInfo used; handle Dash/Dot and fat lines
1010  basegfx::B2DPolygon aPolygon;
1011  aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
1012  aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
1014  }
1015  }
1016  }
1017  break;
1018 
1019  case MetaActionType::RECT:
1020  {
1021  if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1022  {
1023  const MetaRectAction* pA = static_cast<const MetaRectAction*>(pAction);
1024 
1027 
1029  ImplWriteRect( pA->GetRect() );
1030  ImplEndRecord();
1031  }
1032  }
1033  break;
1034 
1036  {
1037  if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1038  {
1039  const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pAction);
1040 
1043 
1045  ImplWriteRect( pA->GetRect() );
1046  ImplWriteSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) );
1047  ImplEndRecord();
1048  }
1049  }
1050  break;
1051 
1053  {
1054  if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1055  {
1056  const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pAction);
1057 
1060 
1062  ImplWriteRect( pA->GetRect() );
1063  ImplEndRecord();
1064  }
1065  }
1066  break;
1067 
1068  case MetaActionType::ARC:
1069  case MetaActionType::PIE:
1070  case MetaActionType::CHORD:
1072  {
1073  if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1074  {
1075  tools::Polygon aPoly;
1076 
1077  switch( nType )
1078  {
1079  case MetaActionType::ARC:
1080  {
1081  const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
1082  aPoly = tools::Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Arc );
1083  }
1084  break;
1085 
1086  case MetaActionType::PIE:
1087  {
1088  const MetaPieAction* pA = static_cast<const MetaPieAction*>(pAction);
1089  aPoly = tools::Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Pie );
1090  }
1091  break;
1092 
1093  case MetaActionType::CHORD:
1094  {
1095  const MetaChordAction* pA = static_cast<const MetaChordAction*>(pAction);
1096  aPoly = tools::Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Chord );
1097  }
1098  break;
1099 
1101  aPoly = static_cast<const MetaPolygonAction*>(pAction)->GetPolygon();
1102  break;
1103  default: break;
1104  }
1105 
1106  ImplWritePolygonRecord( aPoly, nType != MetaActionType::ARC );
1107  }
1108  }
1109  break;
1110 
1112  {
1113  if( maVDev->IsLineColor() )
1114  {
1115  const MetaPolyLineAction* pA = static_cast<const MetaPolyLineAction*>(pAction);
1116  const tools::Polygon& rPoly = pA->GetPolygon();
1117 
1118  if( rPoly.GetSize() )
1119  {
1120  if(pA->GetLineInfo().IsDefault())
1121  {
1122  ImplWritePolygonRecord( rPoly, false );
1123  }
1124  else
1125  {
1126  // LineInfo used; handle Dash/Dot and fat lines
1128  }
1129  }
1130  }
1131  }
1132  break;
1133 
1135  {
1136  if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1137  ImplWritePolyPolygonRecord( static_cast<const MetaPolyPolygonAction*>(pAction)->GetPolyPolygon() );
1138  }
1139  break;
1140 
1142  {
1143  const MetaGradientAction* pA = static_cast<const MetaGradientAction*>(pAction);
1144  GDIMetaFile aTmpMtf;
1145 
1146  maVDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1147  ImplWrite( aTmpMtf );
1148  }
1149  break;
1150 
1151  case MetaActionType::HATCH:
1152  {
1153  const MetaHatchAction* pA = static_cast<const MetaHatchAction*>(pAction);
1154  GDIMetaFile aTmpMtf;
1155 
1156  maVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1157  ImplWrite( aTmpMtf );
1158  }
1159  break;
1160 
1162  {
1163  const tools::PolyPolygon& rPolyPoly = static_cast<const MetaTransparentAction*>(pAction)->GetPolyPolygon();
1164  if( rPolyPoly.Count() )
1165  ImplWritePlusFillPolygonRecord( rPolyPoly[0], static_cast<const MetaTransparentAction*>(pAction)->GetTransparence() );
1168  ImplWritePolyPolygonRecord( rPolyPoly );
1169 
1173  }
1174  break;
1175 
1177  {
1178  const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pAction);
1179 
1180  GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1181  Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1182  const Size aSrcSize( aTmpMtf.GetPrefSize() );
1183  const Point aDestPt( pA->GetPoint() );
1184  const Size aDestSize( pA->GetSize() );
1185  const double fScaleX = aSrcSize.Width() ? static_cast<double>(aDestSize.Width()) / aSrcSize.Width() : 1.0;
1186  const double fScaleY = aSrcSize.Height() ? static_cast<double>(aDestSize.Height()) / aSrcSize.Height() : 1.0;
1187  long nMoveX, nMoveY;
1188 
1189  if( fScaleX != 1.0 || fScaleY != 1.0 )
1190  {
1191  aTmpMtf.Scale( fScaleX, fScaleY );
1192  aSrcPt.setX( FRound( aSrcPt.X() * fScaleX ) );
1193  aSrcPt.setY( FRound( aSrcPt.Y() * fScaleY ) );
1194  }
1195 
1196  nMoveX = aDestPt.X() - aSrcPt.X();
1197  nMoveY = aDestPt.Y() - aSrcPt.Y();
1198 
1199  if( nMoveX || nMoveY )
1200  aTmpMtf.Move( nMoveX, nMoveY );
1201 
1205  ImplWrite( aTmpMtf );
1206  }
1207  break;
1208 
1209  case MetaActionType::EPS:
1210  {
1211  const MetaEPSAction* pA = static_cast<const MetaEPSAction*>(pAction);
1212  const GDIMetaFile& aSubstitute( pA->GetSubstitute() );
1213 
1214  for( size_t i = 0, nCount = aSubstitute.GetActionSize(); i < nCount; i++ )
1215  {
1216  const MetaAction* pSubstAct = aSubstitute.GetAction( i );
1217  if( pSubstAct->GetType() == MetaActionType::BMPSCALE )
1218  {
1219  maVDev->Push();
1221  ImplEndRecord();
1222 
1223  MapMode aMapMode( aSubstitute.GetPrefMapMode() );
1224  Size aOutSize( OutputDevice::LogicToLogic( pA->GetSize(), maVDev->GetMapMode(), aMapMode ) );
1225  aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
1226  aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
1227  aMapMode.SetOrigin( OutputDevice::LogicToLogic( pA->GetPoint(), maVDev->GetMapMode(), aMapMode ) );
1228  maVDev->SetMapMode( aMapMode );
1229  ImplWrite( aSubstitute );
1230 
1231  maVDev->Pop();
1233  m_rStm.WriteInt32( -1 );
1234  ImplEndRecord();
1235  break;
1236  }
1237  }
1238  }
1239  break;
1240 
1241  case MetaActionType::BMP:
1242  {
1243  const MetaBmpAction* pA = static_cast<const MetaBmpAction *>(pAction);
1244  ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), maVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ), WIN_SRCCOPY );
1245  }
1246  break;
1247 
1249  {
1250  const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
1251  ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
1252  }
1253  break;
1254 
1256  {
1257  const MetaBmpScalePartAction* pA = static_cast<const MetaBmpScalePartAction*>(pAction);
1258  Bitmap aTmp( pA->GetBitmap() );
1259 
1260  if( aTmp.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
1261  ImplWriteBmpRecord( aTmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
1262  }
1263  break;
1264 
1265  case MetaActionType::BMPEX:
1266  {
1267  const MetaBmpExAction* pA = static_cast<const MetaBmpExAction *>(pAction);
1268  Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1269  Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1270 
1271  if( !!aMsk )
1272  {
1273  aBmp.Replace( aMsk, COL_WHITE );
1274  aMsk.Invert();
1275  ImplWriteBmpRecord( aMsk, pA->GetPoint(), maVDev->PixelToLogic( aMsk.GetSizePixel() ), WIN_SRCPAINT );
1276  ImplWriteBmpRecord( aBmp, pA->GetPoint(), maVDev->PixelToLogic( aBmp.GetSizePixel() ), WIN_SRCAND );
1277  }
1278  else
1279  ImplWriteBmpRecord( aBmp, pA->GetPoint(), aBmp.GetSizePixel(), WIN_SRCCOPY );
1280  }
1281  break;
1282 
1284  {
1285  const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
1286  Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1287  Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1288 
1289  if( !!aMsk )
1290  {
1291  aBmp.Replace( aMsk, COL_WHITE );
1292  aMsk.Invert();
1293  ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT );
1294  ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND );
1295  }
1296  else
1297  ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
1298  }
1299  break;
1300 
1302  {
1303  const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pAction);
1304  BitmapEx aBmpEx( pA->GetBitmapEx() );
1305  aBmpEx.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1306  Bitmap aBmp( aBmpEx.GetBitmap() );
1307  Bitmap aMsk( aBmpEx.GetMask() );
1308 
1309  if( !!aMsk )
1310  {
1311  aBmp.Replace( aMsk, COL_WHITE );
1312  aMsk.Invert();
1314  ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCAND );
1315  }
1316  else
1317  ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
1318  }
1319  break;
1320 
1321  case MetaActionType::TEXT:
1322  {
1323  const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
1324  const OUString aText = pA->GetText().copy( pA->GetIndex(), std::min(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
1325 
1327  ImplWriteTextRecord( pA->GetPoint(), aText, nullptr, 0 );
1328  }
1329  break;
1330 
1332  {
1333  const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
1334  const OUString& aText( pA->GetText() );
1335 
1337  ImplWriteTextRecord( pA->GetRect().TopLeft(), aText, nullptr, 0 );
1338  }
1339  break;
1340 
1342  {
1343  const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
1344  const OUString aText = pA->GetText().copy( pA->GetIndex(), std::min(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
1345 
1347  ImplWriteTextRecord( pA->GetPoint(), aText, pA->GetDXArray(), 0 );
1348  }
1349  break;
1350 
1352  {
1353  const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pAction);
1354  const OUString aText = pA->GetText().copy( pA->GetIndex(), std::min(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
1355 
1357  ImplWriteTextRecord( pA->GetPoint(), aText, nullptr, pA->GetWidth() );
1358  }
1359  break;
1360 
1362  {
1363  const_cast<MetaAction*>(pAction)->Execute( maVDev );
1364  mbLineChanged = true;
1365  }
1366  break;
1367 
1369  {
1370  const_cast<MetaAction*>(pAction)->Execute( maVDev );
1371  mbFillChanged = true;
1372  }
1373  break;
1374 
1379  case MetaActionType::FONT:
1380  {
1381  const_cast<MetaAction*>(pAction)->Execute( maVDev );
1382  mbTextChanged = true;
1383  }
1384  break;
1385 
1387  {
1388  const_cast<MetaAction*>(pAction)->Execute( maVDev );
1389 
1391  ImplWriteRect( static_cast<const MetaISectRectClipRegionAction*>(pAction)->GetRect() );
1392  ImplEndRecord();
1393  }
1394  break;
1395 
1399  {
1400  const_cast<MetaAction*>(pAction)->Execute( maVDev );
1401  }
1402  break;
1403 
1406  const_cast<MetaAction*>(pAction)->Execute( maVDev );
1407  break;
1408 
1409  case MetaActionType::PUSH:
1410  {
1411  const_cast<MetaAction*>(pAction)->Execute( maVDev );
1412 
1414  ImplEndRecord();
1415  }
1416  break;
1417 
1418  case MetaActionType::POP:
1419  {
1420  const_cast<MetaAction*>(pAction)->Execute( maVDev );
1421 
1423  m_rStm.WriteInt32( -1 );
1424  ImplEndRecord();
1425 
1426  ImplWriteRasterOp( maVDev->GetRasterOp() );
1428  }
1429  break;
1430 
1432  {
1433  const_cast<MetaAction*>(pAction)->Execute( maVDev );
1434  ImplWriteRasterOp( static_cast<const MetaRasterOpAction*>(pAction)->GetRasterOp() );
1435  }
1436  break;
1437 
1439  {
1440  ComplexTextLayoutFlags nLayoutMode = static_cast<const MetaLayoutModeAction*>(pAction)->GetLayoutMode();
1441  mnHorTextAlign = 0;
1443  {
1445  }
1450  break;
1451  }
1452 
1454  {
1455  MetaCommentAction const*const pCommentAction(
1456  static_cast<MetaCommentAction const*>(pAction));
1457  if (pCommentAction->GetComment() == "EMF_PLUS")
1458  {
1460  m_rStm.WriteBytes(pCommentAction->GetData(),
1461  pCommentAction->GetDataSize());
1463  }
1464  }
1465  break;
1466 
1467  case MetaActionType::MASK:
1473  // Explicitly ignored cases
1474  break;
1475 
1476  default:
1477  // TODO: Implement more cases as necessary. Let's not bother with a warning.
1478  break;
1479  }
1480  }
1481 }
1482 
1483 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt16 Count() const
Point TopLeft() const
#define TEXT_SELECT
Definition: emfwr.cxx:86
long Width() const
void ImplEndCommentRecord()
Definition: emfwr.cxx:117
void ImplWriteSize(const Size &rSize)
Definition: emfwr.cxx:601
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:182
sal_uInt32 mnLineHandle
Definition: emfwr.hxx:45
void ImplCheckTextAttr()
Definition: emfwr.cxx:451
void ImplWriteRect(const tools::Rectangle &rRect)
Definition: emfwr.cxx:607
Bitmap GetMask() const
Definition: bitmapex.cxx:258
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:401
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
void ImplWriteExtent(long nExtent)
Definition: emfwr.cxx:589
#define WIN_EMR_ROUNDRECT
Definition: emfwr.cxx:62
sal_Int32 GetLen() const
Definition: metaact.hxx:492
bool IsHeightEmpty() const
const Point & GetPoint() const
Definition: metaact.hxx:700
sal_uInt8 GetRed() const
const OUString & GetFamilyName() const
Definition: font/font.cxx:670
FAMILY_SCRIPT
void ImplBeginPlusRecord(EmfPlusRecordType nType, sal_uInt16 nFlags)
Definition: emfwr.cxx:129
const Point & GetEndPoint() const
Definition: metaact.hxx:337
SvStream & WriteUInt16(sal_uInt16 nUInt16)
std::vector< bool > mHandlesUsed
Definition: emfwr.hxx:37
long FRound(double fVal)
const GDIMetaFile & GetGDIMetaFile() const
Definition: metaact.hxx:1556
void ImplWritePlusFillPolygonRecord(const tools::Polygon &rPoly, sal_uInt32 nTrans)
Definition: emfwr.cxx:224
void ImplWrite(const GDIMetaFile &rMtf)
Definition: emfwr.cxx:948
#define WIN_EMR_SETWINDOWORGEX
Definition: emfwr.cxx:42
const Point & GetSrcPoint() const
Definition: metaact.hxx:738
sal_uInt32 GetVertRound() const
Definition: metaact.hxx:243
SvStream & WriteInt32(sal_Int32 nInt32)
FAMILY_MODERN
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
#define WIN_EMR_SETTEXTALIGN
Definition: emfwr.cxx:50
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1674
#define WIN_EMR_DELETEOBJECT
Definition: emfwr.cxx:59
long Height() const
MapMode maDestMapMode
Definition: emfwr.hxx:35
#define WIN_EMR_BEGINPATH
Definition: emfwr.cxx:64
void ImplWriteTextRecord(const Point &rPos, const OUString &rText, const long *pDXArray, sal_uInt32 nWidth)
Definition: emfwr.cxx:841
void ImplWritePlusColor(const Color &rColor, sal_uInt32 nTrans)
Definition: emfwr.cxx:206
const Point & GetPoint() const
Definition: metaact.hxx:525
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:241
const MapMode & GetPrefMapMode() const
Definition: gdimtf.hxx:176
bool mbLineChanged
Definition: emfwr.hxx:44
void ImplWritePolygonRecord(const tools::Polygon &rPoly, bool bClose)
Definition: emfwr.cxx:619
sal_uIntPtr sal_uLong
const Point & GetPoint() const
Definition: metaact.hxx:1593
WEIGHT_THIN
bool ImplPrepareHandleSelect(sal_uInt32 &rHandle, sal_uLong nSelectType)
Definition: emfwr.cxx:384
#define WIN_EMR_ELLIPSE
Definition: emfwr.cxx:60
#define WIN_EMR_CLOSEFIGURE
Definition: emfwr.cxx:66
const Point & GetPoint() const
Definition: metaact.hxx:1557
bool mbRecordOpen
Definition: emfwr.hxx:42
WEIGHT_BLACK
#define WIN_EMR_CREATEPEN
Definition: emfwr.cxx:57
sal_uInt64 Seek(sal_uInt64 nPos)
#define TA_TOP
Definition: emfwr.cxx:91
const Size & GetSize() const
Definition: metaact.hxx:701
#define WIN_EMR_STROKEPATH
Definition: emfwr.cxx:68
WEIGHT_SEMIBOLD
sal_Int32 GetIndex() const
Definition: metaact.hxx:527
#define WIN_EMR_EOF
Definition: emfwr.cxx:45
#define WIN_EMR_SETTEXTCOLOR
Definition: emfwr.cxx:51
#define WIN_EMR_RESTOREDC
Definition: emfwr.cxx:55
#define WIN_EMR_SETPIXELV
Definition: emfwr.cxx:46
const Point & GetEndPoint() const
Definition: metaact.hxx:181
const OUString & GetText() const
Definition: metaact.hxx:564
FAMILY_ROMAN
Size GetSizePixel() const
sal_uLong mnRecordPos
Definition: emfwr.hxx:40
bool mbTextChanged
Definition: emfwr.hxx:48
const Size & GetSrcSize() const
Definition: metaact.hxx:739
WEIGHT_LIGHT
sal_uInt64 SeekRel(sal_Int64 nPos)
#define WIN_EMR_SETMAPMODE
Definition: emfwr.cxx:47
FontFamily GetFamilyType()
Definition: font/font.cxx:694
FontAlign GetAlignment() const
Definition: font/font.cxx:668
const sal_uInt8 * GetData() const
Definition: metaact.hxx:1655
WEIGHT_BOLD
FontItalic GetItalic()
Definition: font/font.cxx:693
#define WIN_EMR_POLYGON
Definition: emfwr.cxx:36
void ImplCheckFillAttr()
Definition: emfwr.cxx:433
long Right() const
sal_uInt32 mnTextHandle
Definition: emfwr.hxx:49
ErrCode GetError() const
const Point & GetPoint() const
Definition: metaact.hxx:801
void ImplBeginRecord(sal_uInt32 nType)
Definition: emfwr.cxx:348
LINESTYLE_NONE
const OUString & GetText() const
Definition: metaact.hxx:490
void ImplWriteRasterOp(RasterOp eRop)
Definition: emfwr.cxx:573
RasterOp
Definition: vclenum.hxx:191
void ImplReleaseHandle(sal_uLong nHandle)
Definition: emfwr.cxx:342
const Bitmap & GetBitmap() const
Definition: metaact.hxx:667
PolyFlags GetFlags(sal_uInt16 nPos) const
#define WIN_SRCAND
Definition: emfwr.cxx:77
#define MM_ANISOTROPIC
Definition: emfwr.cxx:96
const Gradient & GetGradient() const
Definition: metaact.hxx:981
bool mbRecordPlusOpen
Definition: emfwr.hxx:43
SvStream & WriteUInt32(sal_uInt32 nUInt32)
const Point & GetStartPoint() const
Definition: metaact.hxx:303
#define TA_BASELINE
Definition: emfwr.cxx:93
MetaActionType
#define WIN_SRCINVERT
Definition: emfwr.cxx:78
long Top() const
PITCH_VARIABLE
#define WIN_EMR_SETVIEWPORTEXTEX
Definition: emfwr.cxx:43
const Size & GetSize() const
Definition: metaact.hxx:802
void ImplWritePoint(const Point &rPoint)
Definition: emfwr.cxx:595
ScopedVclPtr< VirtualDevice > maVDev
Definition: emfwr.hxx:34
FAMILY_DECORATIVE
sal_uInt8 GetBlue() const
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:271
#define WIN_SRCCOPY
Definition: emfwr.cxx:75
void ImplWriteColor(const Color &rColor)
Definition: emfwr.cxx:563
sal_uInt32 GetHorzRound() const
Definition: metaact.hxx:242
void ImplWritePlusPoint(const Point &rPoint)
Definition: emfwr.cxx:217
void SetMapUnit(MapUnit eUnit)
Definition: mapmod.cxx:97
Bitmap GetBitmap(const Color *pTransReplaceColor=nullptr) const
Definition: bitmapex.cxx:236
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
#define WIN_EMR_SELECTOBJECT
Definition: emfwr.cxx:56
#define HANDLE_INVALID
Definition: emfwr.cxx:81
void ImplEndPlusRecord()
Definition: emfwr.cxx:143
WEIGHT_SEMILIGHT
def right
EmfPlusRecordType
Definition: emfwr.cxx:98
#define WIN_EMR_SETROP2
Definition: emfwr.cxx:49
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:210
FontPitch GetPitch()
Definition: font/font.cxx:690
const Size & GetPrefSize() const
Definition: gdimtf.hxx:173
const tools::Polygon & GetPolygon() const
Definition: metaact.hxx:400
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:836
const Point & GetDestPoint() const
Definition: metaact.hxx:837
const Point & GetPoint() const
Definition: metaact.hxx:489
PITCH_FIXED
#define TA_RTLREADING
Definition: emfwr.cxx:94
ComplexTextLayoutFlags
Definition: outdevstate.hxx:66
void Impl_handleLineInfoPolyPolygons(const LineInfo &rInfo, const basegfx::B2DPolygon &rLinePolygon)
Definition: emfwr.cxx:912
#define WIN_EMR_POLYPOLYGON
Definition: emfwr.cxx:40
#define WIN_SRCPAINT
Definition: emfwr.cxx:76
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:768
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:980
const OUString & GetText() const
Definition: metaact.hxx:526
int i
QPRO_FUNC_TYPE const nType
#define WIN_EMR_INTERSECTCLIPRECT
Definition: emfwr.cxx:53
const Bitmap & GetBitmap() const
Definition: metaact.hxx:735
WEIGHT_MEDIUM
const Size & GetSize() const
Definition: metaact.hxx:1558
sal_uLong mnRecordCount
Definition: emfwr.hxx:39
sal_uInt32 GetWidth() const
Definition: metaact.hxx:565
void ImplBeginCommentRecord(sal_Int32 nCommentType)
Definition: emfwr.cxx:110
bool HasFlags() const
#define WIN_EMR_GDICOMMENT
Definition: emfwr.cxx:70
std::size_t WriteBytes(const void *pData, std::size_t nSize)
WEIGHT_NORMAL
sal_uInt32 mnHorTextAlign
Definition: emfwr.hxx:50
WEIGHT_ULTRALIGHT
#define TA_RIGHT
Definition: emfwr.cxx:89
long * GetDXArray() const
Definition: metaact.hxx:529
long Bottom() const
const Point & GetEndPoint() const
Definition: metaact.hxx:304
#define WIN_EMR_COMMENT_EMFPLUS
Definition: emfwr.cxx:79
bool WriteEMF(const GDIMetaFile &rMtf)
Definition: emfwr.cxx:239
const Size & GetFontSize() const
Definition: font/font.cxx:673
const OUString & GetText() const
Definition: metaact.hxx:599
void ImplWritePlusEOF()
Definition: emfwr.cxx:199
ALIGN_BOTTOM
#define WIN_EMR_EXTTEXTOUTW
Definition: emfwr.cxx:73
const Point & GetStartPoint() const
Definition: metaact.hxx:369
sal_uInt32 mnFillHandle
Definition: emfwr.hxx:47
FontStrikeout GetStrikeout() const
Definition: font/font.cxx:712
sal_uInt16 GetSize() const
const Point & GetSrcPoint() const
Definition: metaact.hxx:839
sal_Int32 GetLen() const
Definition: metaact.hxx:567
const Point & GetPoint() const
Definition: metaact.hxx:769
WEIGHT_ULTRABOLD
::basegfx::B2DPolygon getB2DPolygon() const
#define WIN_EMR_POLYLINETO
Definition: emfwr.cxx:39
ITALIC_NONE
void ImplWritePolyPolygonRecord(const tools::PolyPolygon &rPolyPoly)
Definition: emfwr.cxx:644
void ImplWritePath(const tools::PolyPolygon &rPolyPoly, bool bClose)
Definition: emfwr.cxx:693
#define WIN_EMR_CREATEBRUSHINDIRECT
Definition: emfwr.cxx:58
long X() const
#define WIN_EMR_ENDPATH
Definition: emfwr.cxx:65
#define WIN_EMR_SETWINDOWEXTEX
Definition: emfwr.cxx:41
const Size & GetSize() const
Definition: metaact.hxx:1594
const Bitmap & GetBitmap() const
Definition: metaact.hxx:699
const Point & GetDestPoint() const
Definition: metaact.hxx:736
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:302
const Size & GetDestSize() const
Definition: metaact.hxx:737
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:368
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1040
void ImplEndRecord()
Definition: emfwr.cxx:362
#define WIN_EMR_STRETCHDIBITS
Definition: emfwr.cxx:71
const Point & GetPoint() const
Definition: metaact.hxx:563
#define WIN_EMR_MOVETOEX
Definition: emfwr.cxx:52
sal_uInt8 GetGreen() const
const Point & GetStartPoint() const
Definition: metaact.hxx:180
#define WIN_EMR_POLYBEZIERTO
Definition: emfwr.cxx:38
ALIGN_TOP
sal_uInt32 GetDataSize() const
Definition: metaact.hxx:1654
short GetOrientation() const
Definition: font/font.cxx:686
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:800
void ImplWriteBmpRecord(const Bitmap &rBmp, const Point &rPt, const Size &rSz, sal_uInt32 nROP)
Definition: emfwr.cxx:778
const Point & GetStartPoint() const
Definition: metaact.hxx:336
sal_uInt32 count() const
const Point & GetPoint() const
Definition: metaact.hxx:120
const Size & GetSrcSize() const
Definition: metaact.hxx:840
#define SAL_WARN_IF(condition, area, stream)
#define ERRCODE_NONE
Definition: errcode.hxx:198
sal_uLong mnHandleCount
Definition: emfwr.hxx:38
FontWeight GetWeight()
Definition: font/font.cxx:691
unsigned char sal_uInt8
MetaAction * GetAction(size_t nAction) const
Definition: gdimtf.cxx:158
#define LINE_SELECT
Definition: emfwr.cxx:84
FAMILY_SWISS
SvStream & WriteUChar(unsigned char nChar)
#define WIN_EMR_RECTANGLE
Definition: emfwr.cxx:61
const Point & GetPoint() const
Definition: metaact.hxx:148
const Point & GetPoint() const
Definition: metaact.hxx:668
SvStream & WriteInt16(sal_Int16 nInt16)
SvStream & m_rStm
Definition: emfwr.hxx:36
#define TA_BOTTOM
Definition: emfwr.cxx:92
sal_uInt64 Tell() const
size_t GetActionSize() const
Definition: gdimtf.cxx:153
void ImplPlusRecord(EmfPlusRecordType nType, sal_uInt16 nFlags)
Definition: emfwr.cxx:159
bool IsWidthEmpty() const
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
MetaActionType GetType() const
Definition: metaact.hxx:89
#define FILL_SELECT
Definition: emfwr.cxx:85
long Left() const
#define WIN_EMR_SETBKMODE
Definition: emfwr.cxx:48
#define WIN_EMR_FILLPATH
Definition: emfwr.cxx:67
const Point & GetEndPoint() const
Definition: metaact.hxx:370
const Hatch & GetHatch() const
Definition: metaact.hxx:1041
const Color & GetColor() const
Definition: metaact.hxx:121
FontLineStyle GetUnderline() const
Definition: font/font.cxx:710
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:335
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
tools::Rectangle GetBoundRect() const
void WriteEMFPlusHeader(const Size &rMtfSizePix, const Size &rMtfSizeLog)
Definition: emfwr.cxx:165
const OString & GetComment() const
Definition: metaact.hxx:1652
#define MAXHANDLES
Definition: emfwr.cxx:82
#define WIN_EMR_LINETO
Definition: emfwr.cxx:63
tools::Rectangle GetBoundRect() const
sal_uLong mnRecordPlusPos
Definition: emfwr.hxx:41
#define BITFIELDS
Definition: dibtools.hxx:37
void reset()=delete
sal_Int32 GetLen() const
Definition: metaact.hxx:528
STRIKEOUT_NONE
bool WriteDIB(const Bitmap &rSource, SvStream &rOStm, bool bCompressed, bool bFileHeader)
Definition: dibtools.cxx:1854
bool Replace(const Bitmap &rMask, const Color &rReplaceColor)
Replace all pixel where the given mask is on with the specified color.
const Size & GetDestSize() const
Definition: metaact.hxx:838
sal_uLong ImplAcquireHandle()
Definition: emfwr.cxx:323
bool mbFillChanged
Definition: emfwr.hxx:46
#define WIN_EMR_POLYLINE
Definition: emfwr.cxx:37
#define WIN_EMR_SAVEDC
Definition: emfwr.cxx:54
const GDIMetaFile & GetSubstitute() const
Definition: metaact.hxx:1592
#define WIN_EMR_SETVIEWPORTORGEX
Definition: emfwr.cxx:44
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: bitmapex.cxx:434
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:598
sal_Int32 GetIndex() const
Definition: metaact.hxx:566
sal_Int32 GetIndex() const
Definition: metaact.hxx:491
#define WIN_EMR_EXTCREATEFONTINDIRECTW
Definition: emfwr.cxx:72
rtl_TextEncoding GetCharSet() const
Definition: font/font.cxx:679
long Y() const
void ImplCheckLineAttr()
Definition: emfwr.cxx:416
const void * GetData()
sal_uInt32 count() const