LibreOffice Module emfio (master) 1
mtftools.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 <mtftools.hxx>
21
22#include <cstdlib>
23#include <memory>
26#include <vcl/metric.hxx>
27#include <vcl/graphictools.hxx>
28#include <vcl/BitmapTools.hxx>
29#include <vcl/metaact.hxx>
30#include <vcl/canvastools.hxx>
31#include <vcl/svapp.hxx>
32#include <tools/stream.hxx>
33#include <rtl/tencinfo.h>
34#include <sal/log.hxx>
35#include <osl/diagnose.h>
36#include <vcl/virdev.hxx>
37#include <o3tl/safeint.hxx>
41
42#if OSL_DEBUG_LEVEL > 1
43#define EMFP_DEBUG(x) x
44#else
45#define EMFP_DEBUG(x)
46#endif
47
48namespace emfio
49{
50 SvStream& operator >> (SvStream& rInStream, XForm& rXForm)
51 {
52 if (sizeof(float) != 4)
53 {
54 OSL_FAIL("EmfReader::sizeof( float ) != 4");
55 rXForm = XForm();
56 }
57 else
58 {
59 rInStream.ReadFloat(rXForm.eM11);
60 rInStream.ReadFloat(rXForm.eM12);
61 rInStream.ReadFloat(rXForm.eM21);
62 rInStream.ReadFloat(rXForm.eM22);
63 rInStream.ReadFloat(rXForm.eDx);
64 rInStream.ReadFloat(rXForm.eDy);
65 }
66 return rInStream;
67 }
68
70 {
71 maClip.intersectPolyPolygon(rPolyPolygon);
72 }
73
75 {
76 maClip.subtractPolyPolygon(rPolyPolygon);
77 }
78
79 void WinMtfClipPath::setClipPath( const basegfx::B2DPolyPolygon& rB2DPoly, RegionMode nClippingMode )
80 {
81 switch ( nClippingMode )
82 {
84 maClip.unionPolyPolygon(rB2DPoly);
85 break;
87 maClip.xorPolyPolygon(rB2DPoly);
88 break;
91 break;
94 break;
97 break;
98 }
99 }
100
102 {
103 basegfx::B2DHomMatrix aTranslate;
104 aTranslate.translate(rSize.Width(), rSize.Height());
105 maClip.transform(aTranslate);
106 }
107
109 {
110 // Empty clip region - everything visible
112 }
113
115 {
116 return maClip.getClipPoly();
117 }
118
119 void WinMtfPathObj::AddPoint( const Point& rPoint )
120 {
121 if ( bClosed )
123 tools::Polygon& rPoly = static_cast<tools::PolyPolygon&>(*this)[ Count() - 1 ];
124 rPoly.Insert( rPoly.GetSize(), rPoint );
125 bClosed = false;
126 }
127
129 {
130 if ( bClosed )
132 tools::Polygon& rPoly = static_cast<tools::PolyPolygon&>(*this)[ Count() - 1 ];
133 rPoly.Insert( rPoly.GetSize(), rPolyLine );
134 bClosed = false;
135 }
136
138 {
139 Insert( rPoly );
140 bClosed = true;
141 }
142
144 {
145 sal_uInt16 i, nCount = rPolyPoly.Count();
146 for ( i = 0; i < nCount; i++ )
147 Insert( rPolyPoly[ i ] );
148 bClosed = true;
149 }
150
152 {
153 if ( Count() )
154 {
155 tools::Polygon& rPoly = static_cast<tools::PolyPolygon&>(*this)[ Count() - 1 ];
156 if ( rPoly.GetSize() > 2 )
157 {
158 Point aFirst( rPoly[ 0 ] );
159 if ( aFirst != rPoly[ rPoly.GetSize() - 1 ] )
160 rPoly.Insert( rPoly.GetSize(), aFirst );
161 }
162 }
163 bClosed = true;
164 }
165
167 {
168 rtl_TextEncoding eCharSet;
169 if ((rFont.alfFaceName == "Symbol")
170 || (rFont.alfFaceName == "MT Extra"))
171 eCharSet = RTL_TEXTENCODING_SYMBOL;
172 else if ((rFont.lfCharSet == DEFAULT_CHARSET) || (rFont.lfCharSet == OEM_CHARSET))
174 rFont.lfCharSet == OEM_CHARSET);
175 else
176 eCharSet = rtl_getTextEncodingFromWindowsCharset( rFont.lfCharSet );
177 if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
178 eCharSet = RTL_TEXTENCODING_MS_1252;
179 aFont.SetCharSet( eCharSet );
181 FontFamily eFamily;
182 switch ( rFont.lfPitchAndFamily >> 4 & 0x0f )
183 {
185 eFamily = FAMILY_ROMAN;
186 break;
187
189 eFamily = FAMILY_SWISS;
190 break;
191
193 eFamily = FAMILY_MODERN;
194 break;
195
197 eFamily = FAMILY_SCRIPT;
198 break;
199
201 eFamily = FAMILY_DECORATIVE;
202 break;
203
204 default:
205 eFamily = FAMILY_DONTKNOW;
206 break;
207 }
208 aFont.SetFamily( eFamily );
209
210 FontPitch ePitch;
211 switch ( rFont.lfPitchAndFamily & 0x0f )
212 {
213 case FIXED_PITCH:
214 ePitch = PITCH_FIXED;
215 break;
216
217 case DEFAULT_PITCH:
218 case VARIABLE_PITCH:
219 default:
220 ePitch = PITCH_VARIABLE;
221 break;
222 }
223 aFont.SetPitch( ePitch );
224
225 FontWeight eWeight;
226 if (rFont.lfWeight == 0) // default weight SHOULD be used
227 eWeight = WEIGHT_DONTKNOW;
228 else if (rFont.lfWeight <= FW_THIN)
229 eWeight = WEIGHT_THIN;
230 else if( rFont.lfWeight <= FW_ULTRALIGHT )
231 eWeight = WEIGHT_ULTRALIGHT;
232 else if( rFont.lfWeight <= FW_LIGHT )
233 eWeight = WEIGHT_LIGHT;
234 else if( rFont.lfWeight < FW_MEDIUM )
235 eWeight = WEIGHT_NORMAL;
236 else if( rFont.lfWeight == FW_MEDIUM )
237 eWeight = WEIGHT_MEDIUM;
238 else if( rFont.lfWeight <= FW_SEMIBOLD )
239 eWeight = WEIGHT_SEMIBOLD;
240 else if( rFont.lfWeight <= FW_BOLD )
241 eWeight = WEIGHT_BOLD;
242 else if( rFont.lfWeight <= FW_ULTRABOLD )
243 eWeight = WEIGHT_ULTRABOLD;
244 else
245 eWeight = WEIGHT_BLACK;
246 aFont.SetWeight( eWeight );
247
248 if( rFont.lfItalic )
250
251 if( rFont.lfUnderline )
253
254 if( rFont.lfStrikeOut )
256
257 aFont.SetOrientation( Degree10(static_cast<sal_Int16>(rFont.lfEscapement)) );
258
259 Size aFontSize( rFont.lfWidth, rFont.lfHeight );
260 if ( rFont.lfHeight > 0 )
261 {
262 // #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
263 SolarMutexGuard aGuard;
265 // converting the cell height into a font height
266 aFont.SetFontSize( aFontSize );
267 pVDev->SetFont( aFont );
268 FontMetric aMetric( pVDev->GetFontMetric() );
269 tools::Long nHeight = aMetric.GetAscent() + aMetric.GetDescent();
270 if (nHeight)
271 {
272 double fHeight = (static_cast<double>(aFontSize.Height()) * rFont.lfHeight ) / nHeight;
273 aFontSize.setHeight( static_cast<sal_Int32>( fHeight + 0.5 ) );
274 }
275 }
276
277 // Convert height to positive
278 aFontSize.setHeight( std::abs(aFontSize.Height()) );
279 aFont.SetFontSize(aFontSize);
280
281 // tdf#127471 adapt nFontWidth from Windows-like notation to
282 // NormedFontScaling if used for text scaling
283#ifndef _WIN32
284 const bool bFontScaledHorizontally(aFontSize.Width() != 0 && aFontSize.Width() != aFontSize.Height());
285
286 if(bFontScaledHorizontally)
287 {
288 // tdf#127471 nFontWidth is the Windows FontScaling, need to convert to
289 // Non-Windowslike notation relative to FontHeight.
290 const tools::Long nAverageFontWidth(aFont.GetOrCalculateAverageFontWidth());
291
292 if(nAverageFontWidth > 0)
293 {
294 const double fScaleFactor(static_cast<double>(aFontSize.Height()) / static_cast<double>(nAverageFontWidth));
295 aFont.SetAverageFontWidth(static_cast<tools::Long>(static_cast<double>(aFontSize.Width()) * fScaleFactor));
296 }
297 }
298#endif
299 };
300
301 // tdf#127471
303 {
304 }
305
307 {
309 {
310 // create average corrected FontScale value and count
311 // positive/negative hits
312 sal_uInt32 nPositive(0);
313 sal_uInt32 nNegative(0);
314 double fAverage(0.0);
315
316 for(double fPart : maAlternativeFontScales)
317 {
318 if(fPart < 0.0)
319 {
320 nNegative++;
321 fAverage += -fPart;
322 }
323 else
324 {
325 nPositive++;
326 fAverage += fPart;
327 }
328 }
329
330 fAverage /= static_cast<double>(maAlternativeFontScales.size());
331
332 if(nPositive >= nNegative)
333 {
334 // correction intended, it is probably an old imported file
336 }
337 else
338 {
339 // correction not favorable in the majority of cases for this Font, still
340 // remember to have a weight in the last decision for correction
342 }
343 }
344
347 }
348
350 {
353
354 if(!rNewMetaFontAction.is())
355 return;
356
357 // check 1st criteria for FontScale active. We usually write this,
358 // so this will already sort out most situations
359 const vcl::Font& rCandidate(rNewMetaFontAction->GetFont());
360
361 if(0 != rCandidate.GetAverageFontWidth())
362 {
363 const tools::Long nUnscaledAverageFontWidth(rCandidate.GetOrCalculateAverageFontWidth());
364
365 // check 2nd (system-dependent) criteria for FontScale
366 if(nUnscaledAverageFontWidth != rCandidate.GetFontHeight())
367 {
368 // FontScale is active, remember and use as current
369 maCurrentMetaFontAction = rNewMetaFontAction;
370 }
371 }
372 }
373
374 void ScaledFontDetectCorrectHelper::evaluateAlternativeFontScale(OUString const & rText, tools::Long nImportedTextLength)
375 {
377 return;
378
379 SolarMutexGuard aGuard; // VirtualDevice is not thread-safe
380 ScopedVclPtrInstance< VirtualDevice > pTempVirtualDevice;
381
382 // calculate measured TextLength
383 const vcl::Font& rFontCandidate(maCurrentMetaFontAction->GetFont());
384 pTempVirtualDevice->SetFont(rFontCandidate);
385 tools::Long nMeasuredTextLength(pTempVirtualDevice->GetTextWidth(rText));
386 // on failure, use original length
387 if (!nMeasuredTextLength)
388 nMeasuredTextLength = nImportedTextLength;
389
390 // compare expected and imported TextLengths
391 if (nImportedTextLength == nMeasuredTextLength)
392 return;
393
394 const double fFactorText(static_cast<double>(nImportedTextLength) / static_cast<double>(nMeasuredTextLength));
395 const double fFactorTextPercent(fabs(1.0 - fFactorText) * 100.0);
396
397 // if we assume that loaded file was written on old linux, we have to
398 // back-convert the scale value depending on which system we run
399#ifdef _WIN32
400 // When running on Windows the value was not adapted at font import (see WinMtfFontStyle
401 // constructor), so it is still NormedFontScaling and we need to convert to Windows-style
402 // scaling
403#else
404 // When running on unx (non-Windows) the value was already adapted at font import (see WinMtfFontStyle
405 // constructor). It was wrongly assumed to be Windows-style FontScaling, so we need to revert that
406 // to get back to the needed unx-style FontScale
407#endif
408 // Interestingly this leads to the *same* correction, so no need to make this
409 // system-dependent (!)
410 const tools::Long nUnscaledAverageFontWidth(rFontCandidate.GetOrCalculateAverageFontWidth());
411 const tools::Long nScaledAverageFontWidth(rFontCandidate.GetAverageFontWidth());
412 const double fScaleFactor(static_cast<double>(nUnscaledAverageFontWidth) / static_cast<double>(rFontCandidate.GetFontHeight()));
413 const double fCorrectedAverageFontWidth(static_cast<double>(nScaledAverageFontWidth) * fScaleFactor);
414 tools::Long nCorrectedTextLength(0);
415
416 { // do in own scope, only need nUnscaledAverageFontWidth
417 vcl::Font rFontCandidate2(rFontCandidate);
418 rFontCandidate2.SetAverageFontWidth(static_cast<tools::Long>(fCorrectedAverageFontWidth));
419 pTempVirtualDevice->SetFont(rFontCandidate2);
420 nCorrectedTextLength = pTempVirtualDevice->GetTextWidth(rText);
421 // on failure, use original length
422 if (!nCorrectedTextLength)
423 nCorrectedTextLength = nImportedTextLength;
424 }
425
426 const double fFactorCorrectedText(static_cast<double>(nImportedTextLength) / static_cast<double>(nCorrectedTextLength));
427 const double fFactorCorrectedTextPercent(fabs(1.0 - fFactorCorrectedText) * 100.0);
428
429 // If FactorCorrectedText fits better than FactorText this is probably
430 // an import of an old EMF/WMF written by LibreOffice on a non-Windows (unx) system
431 // and should be corrected.
432 // Usually in tested cases this lies inside 5% of range, so detecting this just using
433 // fFactorTextPercent inside 5% -> no old file
434 // fFactorCorrectedTextPercent inside 5% -> is old file
435 // works not too bad, but there are some strange not so often used fonts where that
436 // values do deviate, so better just compare if old corrected would fit better than
437 // the uncorrected case, that is usually safe.
438 if(fFactorCorrectedTextPercent < fFactorTextPercent)
439 {
440 maAlternativeFontScales.push_back(fCorrectedAverageFontWidth);
441 }
442 else
443 {
444 // also push, but negative to remember non-fitting case
445 maAlternativeFontScales.push_back(-fCorrectedAverageFontWidth);
446 }
447 }
448
450 {
451 // make sure last evtl. detected current FontAction gets added to identified cases
453
454 // Take final decision to correct FontScaling for this imported Metafile or not.
455 // It is possible to weight positive against negative cases, so to only finally
456 // correct when more positive cases were detected.
457 // But that would be inconsequent and wrong. *If* the detected case is an old import
458 // the whole file was written with wrong FontScale values and all Font actions
459 // need to be corrected. Thus, for now, correct all when there are/is positive
460 // cases detected.
461 // On the other hand it *may* be that for some strange fonts there is a false-positive
462 // in the positive cases, so at least insist on positive cases being more than negative.
463 // Still, do then correct *all* cases.
464 if(!maPositiveIdentifiedCases.empty()
466 {
467 for(std::pair<rtl::Reference<MetaFontAction>, double>& rCandidate : maPositiveIdentifiedCases)
468 {
469 rCandidate.first->correctFontScale(static_cast<tools::Long>(rCandidate.second));
470 }
471 for(std::pair<rtl::Reference<MetaFontAction>, double>& rCandidate : maNegativeIdentifiedCases)
472 {
473 rCandidate.first->correctFontScale(static_cast<tools::Long>(rCandidate.second));
474 }
475 }
476
479 }
480
482 {
483 sal_uInt32 nColor(0);
484 mpInputStream->ReadUInt32( nColor );
485 Color aColor( COL_BLACK );
486 if ( ( nColor & 0xFFFF0000 ) == 0x01000000 )
487 {
488 size_t index = nColor & 0x0000FFFF;
489 if ( index < maPalette.aPaletteColors.size() )
490 aColor = maPalette.aPaletteColors[ index ];
491 else
492 SAL_INFO( "emfio", "\t\t Palette index out of range: " << index );
493 }
494 else
495 aColor = Color( static_cast<sal_uInt8>( nColor ), static_cast<sal_uInt8>( nColor >> 8 ), static_cast<sal_uInt8>( nColor >> 16 ) );
496
497 SAL_INFO("emfio", "\t\tColor: " << aColor);
498 return aColor;
499 };
500
501 Point MtfTools::ImplScale(const Point& rPoint) // Hack to set varying defaults for incompletely defined files.
502 {
503 if (!mbIsMapDevSet)
504 return Point(rPoint.X() * UNDOCUMENTED_WIN_RCL_RELATION - mrclFrame.Left(),
506 else
507 return rPoint;
508 }
509
511 {
512 if ( mnWinExtX && mnWinExtY )
513 {
514 double fX = rPt.X();
515 double fY = rPt.Y();
516
517 double fX2 = fX * maXForm.eM11 + fY * maXForm.eM21 + maXForm.eDx;
518 double fY2 = fX * maXForm.eM12 + fY * maXForm.eM22 + maXForm.eDy;
519
521 {
522 fX2 -= mnWinOrgX;
523 fY2 -= mnWinOrgY;
524
525 switch( meMapMode )
526 {
528 {
531 }
532 break;
534 {
537 }
538 break;
540 {
543 }
544 break;
546 {
549 }
550 break;
551 case MappingMode::MM_HIMETRIC : // in hundredth of a millimeter
552 {
553 fY2 *= -1;
554 }
555 break;
556 default :
557 {
558 if (mnPixX == 0 || mnPixY == 0)
559 {
560 SAL_WARN("emfio", "invalid scaling factor");
561 return Point();
562 }
563 else
564 {
566 {
567 fX2 /= mnWinExtX;
568 fY2 /= mnWinExtY;
569 fX2 *= mnDevWidth;
570 fY2 *= mnDevHeight;
571 }
572 fX2 *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
573 fY2 *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
574 }
575 }
576 break;
577 }
578
579 double nDevOrgX = mnDevOrgX;
580 if (mnPixX)
581 nDevOrgX *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
582 fX2 += nDevOrgX;
583 double nDevOrgY = mnDevOrgY;
584 if (mnPixY)
585 nDevOrgY *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
586 fY2 += nDevOrgY;
587
588 fX2 -= mrclFrame.Left();
589 fY2 -= mrclFrame.Top();
590 }
591 return Point(basegfx::fround(fX2), basegfx::fround(fY2));
592 }
593 else
594 return Point();
595 };
596
597 Size MtfTools::ImplMap(const Size& rSz, bool bDoWorldTransform)
598 {
599 if ( mnWinExtX && mnWinExtY )
600 {
601 // #i121382# apply the whole WorldTransform, else a rotation will be misinterpreted
602 double fWidth, fHeight;
603 if (bDoWorldTransform)
604 {
605 fWidth = rSz.Width() * maXForm.eM11 + rSz.Height() * maXForm.eM21;
606 fHeight = rSz.Width() * maXForm.eM12 + rSz.Height() * maXForm.eM22;
607 }
608 else
609 {
610 //take the scale, but not the rotation
613 basegfx::B2DTuple aScale, aTranslate;
614 double fRotate, fShearX;
615 if (!aMatrix.decompose(aScale, aTranslate, fRotate, fShearX))
616 {
617 aScale.setX(1.0);
618 aScale.setY(1.0);
619 }
620 fWidth = rSz.Width() * aScale.getX();
621 fHeight = rSz.Height() * aScale.getY();
622 }
623
625 {
626 switch( meMapMode )
627 {
629 {
632 }
633 break;
635 {
638 }
639 break;
641 {
644 }
645 break;
646 case MappingMode::MM_HIMETRIC : // in hundredth of millimeters
647 {
648 fHeight *= -1;
649 }
650 break;
652 {
655 }
656 break;
657 default :
658 {
659 if (mnPixX == 0 || mnPixY == 0)
660 {
661 SAL_WARN("emfio", "invalid scaling factor");
662 return Size();
663 }
664 else
665 {
667 {
668 fWidth /= mnWinExtX;
669 fHeight /= mnWinExtY;
670 fWidth *= mnDevWidth;
671 fHeight *= mnDevHeight;
672 }
673 fWidth *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
674 fHeight *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
675 }
676 }
677 break;
678 }
679 }
680 return Size(basegfx::fround(fWidth), basegfx::fround(fHeight));
681 }
682 else
683 return Size();
684 }
685
687 {
688 tools::Rectangle aRect;
689 aRect.SetPos(ImplMap(rRect.TopLeft()));
690 aRect.SaturatingSetSize(ImplMap(rRect.GetSize()));
691 return aRect;
692 }
693
695 {
696 // !!! HACK: we now always set the width to zero because the OS width is interpreted differently;
697 // must later be made portable in SV (KA 1996-02-08)
698 Size aFontSize = ImplMap (rFont.GetFontSize(), false);
699
700 const auto nHeight = aFontSize.Height();
701 if (nHeight < 0)
702 aFontSize.setHeight( o3tl::saturating_toggle_sign(nHeight) );
703
704 rFont.SetFontSize( aFontSize );
705
706 sal_Int32 nResult;
707 const bool bFail = o3tl::checked_multiply(mnWinExtX, mnWinExtY, nResult);
708 if (!bFail && nResult < 0)
709 rFont.SetOrientation( 3600_deg10 - rFont.GetOrientation() );
710 }
711
713 {
714 sal_uInt16 nPoints = rPolygon.GetSize();
715 for ( sal_uInt16 i = 0; i < nPoints; i++ )
716 {
717 rPolygon[ i ] = ImplMap( rPolygon[ i ] );
718 }
719 return rPolygon;
720 }
721
723 {
724 sal_uInt16 nPoints = rPolygon.GetSize();
725 for ( sal_uInt16 i = 0; i < nPoints; i++ )
726 {
727 rPolygon[ i ] = ImplScale( rPolygon[ i ] );
728 }
729 }
730
732 {
733 sal_uInt16 nPolys = rPolyPolygon.Count();
734 for (sal_uInt16 i = 0; i < nPolys; ++i)
735 {
736 ImplScale(rPolyPolygon[i]);
737 }
738 return rPolyPolygon;
739 }
740
742 {
743 sal_uInt16 nPolys = rPolyPolygon.Count();
744 for ( sal_uInt16 i = 0; i < nPolys; ImplMap( rPolyPolygon[ i++ ] ) ) ;
745 return rPolyPolygon;
746 }
747
748 void MtfTools::SelectObject( sal_uInt32 nIndex )
749 {
751 {
752 SAL_INFO ( "emfio", "\t\t ENHMETA_STOCK_OBJECT, StockObject Enumeration: 0x" << std::hex << nIndex );
753 StockObject nStockId = static_cast<StockObject>(nIndex & 0xFF);
754 switch( nStockId )
755 {
757 {
759 mbFillStyleSelected = true;
760 }
761 break;
763 {
765 mbFillStyleSelected = true;
766 }
767 break;
769 {
771 mbFillStyleSelected = true;
772 }
773 break;
775 {
777 mbFillStyleSelected = true;
778 }
779 break;
781 {
783 mbFillStyleSelected = true;
784 }
785 break;
787 {
789 mbFillStyleSelected = true;
790 }
791 break;
793 {
795 }
796 break;
798 {
800 }
801 break;
803 {
805 }
806 break;
807 default:
808 break;
809 }
810 }
811 else
812 {
813 nIndex &= 0xffff; // safety check: don't allow index to be > 65535
814
815 GDIObj *pGDIObj = nullptr;
816
817 if ( nIndex < mvGDIObj.size() )
818 pGDIObj = mvGDIObj[ nIndex ].get();
819
820 if ( pGDIObj )
821 {
822
823 SAL_INFO ( "emfio", "\t\t Index: " << nIndex );
824 if (const auto pen = dynamic_cast<WinMtfLineStyle*>(pGDIObj))
825 {
826 maLineStyle = *pen;
827 SAL_INFO ( "emfio", "\t Line Style, Color: 0x" << std::hex << maLineStyle.aLineColor
828 << ", Weight: " << maLineStyle.aLineInfo.GetWidth() );
829 }
830 else if (const auto brush = dynamic_cast<WinMtfFillStyle*>(
831 pGDIObj))
832 {
833 maFillStyle = *brush;
834 mbFillStyleSelected = true;
835 SAL_INFO("emfio", "\t\tBrush Object, Index: " << nIndex << ", Color: " << maFillStyle.aFillColor);
836 }
837 else if (const auto font = dynamic_cast<WinMtfFontStyle*>(
838 pGDIObj))
839 {
840 maFont = font->aFont;
841 SAL_INFO("emfio", "\t\tFont Object, Index: " << nIndex << ", Font: " << maFont.GetFamilyName() << " " << maFont.GetStyleName());
842 }
843 else if (const auto palette = dynamic_cast<WinMtfPalette*>(
844 pGDIObj))
845 {
846 maPalette = palette->aPaletteColors;
847 SAL_INFO("emfio", "\t\tPalette Object, Index: " << nIndex << ", Number of colours: " << maPalette.aPaletteColors.size() );
848 }
849 }
850 else
851 {
852 SAL_WARN("emfio", "Warning: Unable to find Object with index:" << nIndex);
853 }
854 }
855 }
856
858 {
859 mnTextLayoutMode = nTextLayoutMode;
860 }
861
862 void MtfTools::SetArcDirection(bool bClockWise)
863 {
864 SAL_INFO("emfio", "\t\t Arc direction: " << (bClockWise ? "ClockWise" : "CounterClockWise"));
865 mbClockWiseArcDirection = bClockWise;
866 }
867
869 {
870 mnBkMode = nMode;
871 }
872
873 void MtfTools::SetBkColor( const Color& rColor )
874 {
875 maBkColor = rColor;
876 }
877
878 void MtfTools::SetTextColor( const Color& rColor )
879 {
880 maTextColor = rColor;
881 }
882
883 void MtfTools::SetTextAlign( sal_uInt32 nAlign )
884 {
885 mnTextAlign = nAlign;
886 }
887
888 void MtfTools::ImplResizeObjectArry( sal_uInt32 nNewEntrys )
889 {
890 mvGDIObj.resize(nNewEntrys);
891 }
892
894 {
895 if ( !rPolyPoly.Count() )
896 return;
897
899 if ( rPolyPoly.Count() == 1 )
900 {
901 if ( rPolyPoly.IsRect() )
902 mpGDIMetaFile->AddAction( new MetaRectAction( rPolyPoly.GetBoundRect() ) );
903 else
904 {
905 tools::Polygon aPoly( rPolyPoly[ 0 ] );
906 sal_uInt16 nCount = aPoly.GetSize();
907 if ( nCount )
908 {
909 if ( aPoly[ nCount - 1 ] != aPoly[ 0 ] )
910 {
911 Point aPoint( aPoly[ 0 ] );
912 aPoly.Insert( nCount, aPoint );
913 }
914 mpGDIMetaFile->AddAction( new MetaPolygonAction( std::move(aPoly) ) );
915 }
916 }
917 }
918 else
919 mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
920 }
921
922 void MtfTools::CreateObject( std::unique_ptr<GDIObj> pObject )
923 {
924 if ( pObject )
925 {
926 const auto pLineStyle = dynamic_cast<WinMtfLineStyle*>(pObject.get());
927 const auto pFontStyle = dynamic_cast<WinMtfFontStyle*>(pObject.get());
928
929 if ( pFontStyle )
930 {
931 if (pFontStyle->aFont.GetFontHeight() == 0)
932 pFontStyle->aFont.SetFontHeight(423);
933 ImplMap(pFontStyle->aFont); // defaulting to 12pt
934 }
935 else if ( pLineStyle )
936 {
937 Size aSize(pLineStyle->aLineInfo.GetWidth(), 0);
938 aSize = ImplMap(aSize);
939 pLineStyle->aLineInfo.SetWidth(aSize.Width());
940 }
941 }
942 std::vector<std::unique_ptr<GDIObj>>::size_type nIndex;
943 for ( nIndex = 0; nIndex < mvGDIObj.size(); nIndex++ )
944 {
945 if ( !mvGDIObj[ nIndex ] )
946 break;
947 }
948 if ( nIndex == mvGDIObj.size() )
949 ImplResizeObjectArry( mvGDIObj.size() + 16 );
950
951 mvGDIObj[ nIndex ] = std::move(pObject);
952 }
953
954 void MtfTools::CreateObjectIndexed( sal_uInt32 nIndex, std::unique_ptr<GDIObj> pObject )
955 {
956 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) != 0 )
957 return;
958
959 nIndex &= 0xffff; // safety check: do not allow index to be > 65535
960 if ( pObject )
961 {
962 const auto pLineStyle = dynamic_cast<WinMtfLineStyle*>(pObject.get());
963 const auto pFontStyle = dynamic_cast<WinMtfFontStyle*>(pObject.get());
964 if ( pFontStyle )
965 {
966 if (pFontStyle->aFont.GetFontHeight() == 0)
967 pFontStyle->aFont.SetFontHeight(423);
968 ImplMap(pFontStyle->aFont);
969 }
970 else if ( pLineStyle )
971 {
972 Size aSize(pLineStyle->aLineInfo.GetWidth(), 0);
973 pLineStyle->aLineInfo.SetWidth( ImplMap(aSize).Width() );
974
975 if ( pLineStyle->aLineInfo.GetStyle() == LineStyle::Dash )
976 {
977 aSize.AdjustWidth(1 );
978 tools::Long nDotLen = ImplMap( aSize ).Width();
979 pLineStyle->aLineInfo.SetDistance( nDotLen );
980 pLineStyle->aLineInfo.SetDotLen( nDotLen );
981 pLineStyle->aLineInfo.SetDashLen( nDotLen * 3 );
982 }
983 }
984 }
985 if ( nIndex >= mvGDIObj.size() )
987
988 mvGDIObj[ nIndex ] = std::move(pObject);
989 }
990
992 {
993 CreateObject(std::make_unique<GDIObj>());
994 }
995
996 void MtfTools::DeleteObject( sal_uInt32 nIndex )
997 {
998 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
999 {
1000 if ( nIndex < mvGDIObj.size() )
1001 {
1002 mvGDIObj[ nIndex ].reset();
1003 }
1004 }
1005 }
1006
1008 {
1010 return;
1011 mbClipNeedsUpdate=true;
1012 if ((rRect.Left()-rRect.Right()==0) && (rRect.Top()-rRect.Bottom()==0))
1013 {
1014 return; // empty rectangles cause trouble
1015 }
1016 tools::Polygon aPoly( rRect );
1017 const tools::PolyPolygon aPolyPolyRect( ImplMap( aPoly ) );
1018 maClipPath.intersectClip( aPolyPolyRect.getB2DPolyPolygon() );
1019 }
1020
1022 {
1024 return;
1025 mbClipNeedsUpdate=true;
1026 tools::Polygon aPoly( rRect );
1027 const tools::PolyPolygon aPolyPolyRect( ImplMap( aPoly ) );
1028 maClipPath.excludeClip( aPolyPolyRect.getB2DPolyPolygon() );
1029 }
1030
1031 void MtfTools::MoveClipRegion( const Size& rSize )
1032 {
1034 return;
1035 mbClipNeedsUpdate=true;
1036 maClipPath.moveClipRegion( ImplMap( rSize ) );
1037 }
1038
1039 void MtfTools::SetClipPath( const tools::PolyPolygon& rPolyPolygon, RegionMode eClippingMode, bool bIsMapped )
1040 {
1042 return;
1043 mbClipNeedsUpdate = true;
1044 tools::PolyPolygon aPolyPolygon(rPolyPolygon);
1045
1046 if (!bIsMapped)
1047 {
1048 if (!mbIsMapDevSet && (meMapMode == MappingMode::MM_ISOTROPIC || meMapMode == MappingMode::MM_ANISOTROPIC))
1049 aPolyPolygon = ImplScale(aPolyPolygon);
1050 else
1051 aPolyPolygon = ImplMap(aPolyPolygon);
1052 }
1053 maClipPath.setClipPath(aPolyPolygon.getB2DPolyPolygon(), eClippingMode);
1054 }
1055
1057 {
1058 mbClipNeedsUpdate = true;
1060 }
1061
1062 MtfTools::MtfTools( GDIMetaFile& rGDIMetaFile, SvStream& rStreamWMF)
1063 : mnLatestTextAlign(90),
1065 maLatestBkColor(ColorTransparency, 0x12345678),
1066 maBkColor(COL_WHITE),
1067 mnLatestTextLayoutMode(vcl::text::ComplexTextLayoutFlags::Default),
1068 mnTextLayoutMode(vcl::text::ComplexTextLayoutFlags::Default),
1069 mnLatestBkMode(BackgroundMode::NONE),
1070 mnBkMode(BackgroundMode::OPAQUE),
1071 meLatestRasterOp(RasterOp::Invert),
1072 meRasterOp(RasterOp::OverPaint),
1073 mnRop(),
1074 meGfxMode(GraphicsMode::GM_COMPATIBLE),
1075 meMapMode(MappingMode::MM_TEXT),
1076 mnDevOrgX(0),
1077 mnDevOrgY(0),
1078 mnDevWidth(1),
1079 mnDevHeight(1),
1080 mnWinOrgX(0),
1081 mnWinOrgY(0),
1082 mnWinExtX(1),
1083 mnWinExtY(1),
1084 mnPixX(100),
1085 mnPixY(100),
1086 mnMillX(1),
1087 mnMillY(1),
1088 mpGDIMetaFile(&rGDIMetaFile),
1089 mpInputStream(&rStreamWMF),
1090 mnStartPos(0),
1091 mnEndPos(0),
1092 mbNopMode(false),
1093 mbClockWiseArcDirection(false),
1094 mbFillStyleSelected(false),
1095 mbClipNeedsUpdate(true),
1096 mbComplexClip(false),
1097 mbIsMapWinSet(false),
1098 mbIsMapDevSet(false)
1099 {
1101
1102 if (pLB)
1103 {
1104 pLB->SetSynchronMode();
1105 }
1106
1108 SetDevOrg(Point());
1109
1110 mpGDIMetaFile->AddAction( new MetaPushAction( vcl::PushFlags::CLIPREGION ) ); // The original clipregion has to be on top
1111 // of the stack so it can always be restored
1112 // this is necessary to be able to support
1113 // SetClipRgn( NULL ) and similar ClipRgn actions (SJ)
1114
1115 maFont.SetFamilyName( "Arial" ); // sj: #i57205#, we do have some scaling problems if using
1116 maFont.SetCharSet( RTL_TEXTENCODING_MS_1252 ); // the default font then most times a x11 font is used, we
1117 maFont.SetFontHeight( 423 ); // will prevent this defining a font
1118
1119 maLatestLineStyle.aLineColor = Color( 0x12, 0x34, 0x56 );
1120 maLatestFillStyle.aFillColor = Color( 0x12, 0x34, 0x56 );
1121
1123 meRasterOp = RasterOp::OverPaint;
1124 mpGDIMetaFile->AddAction( new MetaRasterOpAction( RasterOp::OverPaint ) );
1125 }
1126
1127 MtfTools::~MtfTools() COVERITY_NOEXCEPT_FALSE
1128 {
1130 mpGDIMetaFile->SetPrefMapMode(MapMode(MapUnit::Map100thMM));
1131 if ( mrclFrame.IsEmpty() )
1133 else
1135 }
1136
1138 {
1139 if (!mbClipNeedsUpdate)
1140 return;
1141
1142 mbClipNeedsUpdate = false;
1143 mbComplexClip = false;
1144
1145 mpGDIMetaFile->AddAction( new MetaPopAction() ); // taking the original clipregion
1147
1148 // skip for 'no clipping at all' case
1149 if( maClipPath.isEmpty() )
1150 return;
1151
1152 const basegfx::B2DPolyPolygon& rClipPoly( maClipPath.getClipPath() );
1153
1154 mbComplexClip = rClipPoly.count() > 1
1155 || !basegfx::utils::isRectangle(rClipPoly);
1156
1157 // This makes cases like tdf#45820 work in reasonable time.
1158 if (mbComplexClip)
1159 {
1162 vcl::Region(rClipPoly)));
1163 mbComplexClip = false;
1164 }
1165 else
1166 {
1170 rClipPoly.getB2DRange())));
1171 }
1172 }
1173
1175 {
1176 WinMtfLineStyle aTransparentLine( COL_TRANSPARENT, true );
1177 if ( ! ( maLatestLineStyle == aTransparentLine ) )
1178 {
1179 maLatestLineStyle = aTransparentLine;
1180 mpGDIMetaFile->AddAction( new MetaLineColorAction( aTransparentLine.aLineColor, !aTransparentLine.bTransparent ) );
1181 }
1182 }
1183
1185 {
1186 if (!( maLatestLineStyle == maLineStyle ) )
1187 {
1190 }
1191 }
1192
1194 {
1195 if ( !mbFillStyleSelected ) // SJ: #i57205# taking care of bkcolor if no brush is selected
1197 if (!( maLatestFillStyle == maFillStyle ) )
1198 {
1202 }
1203 }
1204
1206 {
1207 WMFRasterOp nRetROP = mnRop;
1208 if ( nRasterOp != mnRop )
1209 {
1210 mnRop = nRasterOp;
1211
1212 if ( mbNopMode && ( nRasterOp != WMFRasterOp::Nop ) )
1213 { // changing modes from WMFRasterOp::Nop so set pen and brush
1216 mbNopMode = false;
1217 }
1218 switch( nRasterOp )
1219 {
1220 case WMFRasterOp::Not:
1221 meRasterOp = RasterOp::Invert;
1222 break;
1223
1225 meRasterOp = RasterOp::Xor;
1226 break;
1227
1228 case WMFRasterOp::Nop:
1229 {
1230 meRasterOp = RasterOp::OverPaint;
1231 if( !mbNopMode )
1232 {
1237 mbNopMode = true;
1238 }
1239 }
1240 break;
1241
1242 default:
1243 meRasterOp = RasterOp::OverPaint;
1244 break;
1245 }
1246 }
1247 if ( nRetROP != nRasterOp )
1249 return nRetROP;
1250 };
1251
1252 void MtfTools::StrokeAndFillPath( bool bStroke, bool bFill )
1253 {
1254 if ( !maPathObj.Count() )
1255 return;
1256
1260 if ( bFill )
1261 {
1262 if ( !bStroke )
1263 {
1266 }
1267 if ( maPathObj.Count() == 1 )
1269 else
1271
1272 if ( !bStroke )
1274 }
1275 // tdf#142014 By default the stroke is made with hairline. If width is bigger, we need to use PolyLineAction
1276 if ( bStroke )
1277 {
1278 // bFill is drawing hairstyle line. So we need to draw it only when the width is different than 0
1279 if ( !bFill || maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
1280 {
1281 sal_uInt16 i, nCount = maPathObj.Count();
1282 for ( i = 0; i < nCount; i++ )
1284 }
1285 }
1286 ClearPath();
1287 }
1288
1289 void MtfTools::DrawPixel( const Point& rSource, const Color& rColor )
1290 {
1291 mpGDIMetaFile->AddAction( new MetaPixelAction( ImplMap( rSource), rColor ) );
1292 }
1293
1294 void MtfTools::MoveTo( const Point& rPoint, bool bRecordPath )
1295 {
1296 Point aDest( ImplMap( rPoint ) );
1297 if ( bRecordPath )
1298 {
1299 // fdo#57353 create new subpath for subsequent moves
1300 if ( maPathObj.Count() )
1301 if ( maPathObj[ maPathObj.Count() - 1 ].GetSize() )
1303 maPathObj.AddPoint( aDest );
1304 }
1305 maActPos = aDest;
1306 }
1307
1308 void MtfTools::LineTo( const Point& rPoint, bool bRecordPath )
1309 {
1311 Point aDest( ImplMap( rPoint ) );
1312 if ( bRecordPath )
1313 maPathObj.AddPoint( aDest );
1314 else
1315 {
1318 }
1319 maActPos = aDest;
1320 }
1321
1323 {
1324 WinMtfFillStyle aFillStyleBackup = maFillStyle;
1325 bool aTransparentBackup = maLineStyle.bTransparent;
1326 BackgroundMode mnBkModeBackup = mnBkMode;
1327
1328 const tools::Polygon aPoly( rRect );
1333 DrawPolygon(aPoly, false);
1334 mnBkMode = mnBkModeBackup; // The rectangle needs to be always drawned even if mode is transparent
1335 maFillStyle = aFillStyleBackup;
1336 maLineStyle.bTransparent = aTransparentBackup;
1337 }
1338
1339 void MtfTools::DrawRect( const tools::Rectangle& rRect, bool bEdge )
1340 {
1343
1344 if ( mbComplexClip )
1345 {
1346 tools::Polygon aPoly( ImplMap( rRect ) );
1347 tools::PolyPolygon aPolyPolyRect( aPoly );
1348 tools::PolyPolygon aDest;
1349 tools::PolyPolygon(maClipPath.getClipPath()).GetIntersection( aPolyPolyRect, aDest );
1351 }
1352 else
1353 {
1354 if ( bEdge )
1355 {
1356 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
1357 {
1359 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
1362 }
1363 else
1364 {
1366 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
1367 }
1368 }
1369 else
1370 {
1372 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
1373 }
1374 }
1375 }
1376
1377 void MtfTools::DrawRoundRect( const tools::Rectangle& rRect, const Size& rSize )
1378 {
1382 mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), std::abs( ImplMap( rSize ).Width() ), std::abs( ImplMap( rSize ).Height() ) ) );
1383 // tdf#142139 Wrong line width during WMF import
1384 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
1385 {
1386 tools::Polygon aRoundRectPoly( rRect, rSize.Width(), rSize.Height() );
1388 }
1389 }
1390
1392 {
1395
1396 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
1397 {
1398 Point aCenter( ImplMap( rRect.Center() ) );
1399 Size aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) );
1400
1404 mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( std::move(aCenter), aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
1405 }
1406 else
1407 {
1410 }
1411 }
1412
1413 void MtfTools::DrawArc( const tools::Rectangle& rRect, const Point& rStart, const Point& rEnd, bool bTo )
1414 {
1418
1419 tools::Rectangle aRect( ImplMap( rRect ) );
1420 Point aStart( ImplMap( rStart ) );
1421 Point aEnd( ImplMap( rEnd ) );
1422
1423 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
1424 {
1425 if ( aStart == aEnd )
1426 { // SJ: #i53768# if start & end is identical, then we have to draw a full ellipse
1427 Point aCenter( aRect.Center() );
1428 Size aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
1429
1430 mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( std::move(aCenter), aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
1431 }
1432 else
1433 mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Arc ), maLineStyle.aLineInfo ) );
1434 }
1435 else
1436 mpGDIMetaFile->AddAction( new MetaArcAction( aRect, aStart, aEnd ) );
1437
1438 if ( bTo )
1439 maActPos = aEnd;
1440 }
1441
1442 void MtfTools::DrawPie( const tools::Rectangle& rRect, const Point& rStart, const Point& rEnd )
1443 {
1446
1447 tools::Rectangle aRect( ImplMap( rRect ) );
1448 Point aStart( ImplMap( rStart ) );
1449 Point aEnd( ImplMap( rEnd ) );
1450
1451 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
1452 {
1454 mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
1456 mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Pie ), maLineStyle.aLineInfo ) );
1457 }
1458 else
1459 {
1461 mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
1462 }
1463 }
1464
1465 void MtfTools::DrawChord( const tools::Rectangle& rRect, const Point& rStart, const Point& rEnd )
1466 {
1469
1470 tools::Rectangle aRect( ImplMap( rRect ) );
1471 Point aStart( ImplMap( rStart ) );
1472 Point aEnd( ImplMap( rEnd ) );
1473
1474 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
1475 {
1477 mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
1479 mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Chord ), maLineStyle.aLineInfo ) );
1480 }
1481 else
1482 {
1484 mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
1485 }
1486 }
1487
1488 void MtfTools::DrawPolygon( tools::Polygon rPolygon, bool bRecordPath )
1489 {
1491 ImplMap( rPolygon );
1492 if ( bRecordPath )
1493 maPathObj.AddPolygon( rPolygon );
1494 else
1495 {
1497
1498 if ( mbComplexClip )
1499 {
1500 tools::PolyPolygon aPolyPoly( rPolygon );
1501 auto tmp = maClipPath.getClip();
1502 tmp.intersectPolyPolygon(aPolyPoly.getB2DPolyPolygon());
1503 tools::PolyPolygon aDest(tmp.getClipPoly());
1505 }
1506 else
1507 {
1508 if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
1509 {
1510 sal_uInt16 nCount = rPolygon.GetSize();
1511 if ( nCount )
1512 {
1513 if ( rPolygon[ nCount - 1 ] != rPolygon[ 0 ] )
1514 {
1515 Point aPoint( rPolygon[ 0 ] );
1516 rPolygon.Insert( nCount, aPoint );
1517 }
1518 }
1520 mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
1523 }
1524 else
1525 {
1527
1529 mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
1530 else {
1531 SvtGraphicFill aFill( tools::PolyPolygon( rPolygon ),
1532 Color(),
1533 0.0,
1537 true,
1539 Color(),
1541 Color(),
1542 Color(),
1543 0,
1545
1546 SvMemoryStream aMemStm;
1547
1548 WriteSvtGraphicFill( aMemStm, aFill );
1549
1550 mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1551 static_cast<const sal_uInt8*>(aMemStm.GetData()),
1552 aMemStm.TellEnd() ) );
1553 mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_END" ) );
1554 }
1555
1556 }
1557 }
1558 }
1559 }
1560
1561 void MtfTools::DrawPolyPolygon( tools::PolyPolygon& rPolyPolygon, bool bRecordPath )
1562 {
1564
1565 ImplMap( rPolyPolygon );
1566
1567 if ( bRecordPath )
1568 maPathObj.AddPolyPolygon( rPolyPolygon );
1569 else
1570 {
1572
1573 if ( mbComplexClip )
1574 {
1575 tools::PolyPolygon aDest;
1576 tools::PolyPolygon(maClipPath.getClipPath()).GetIntersection( rPolyPolygon, aDest );
1578 }
1579 else
1580 {
1582 mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) );
1583 if (maLineStyle.aLineInfo.GetWidth() > 0 || maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash)
1584 {
1585 for (sal_uInt16 nPoly = 0; nPoly < rPolyPolygon.Count(); ++nPoly)
1586 {
1588 }
1589 }
1590 }
1591 }
1592 }
1593
1594 void MtfTools::DrawPolyLine( tools::Polygon rPolygon, bool bTo, bool bRecordPath )
1595 {
1597
1598 sal_uInt16 nPoints = rPolygon.GetSize();
1599 if (nPoints < 1)
1600 return;
1601
1602 ImplMap( rPolygon );
1603 if ( bTo )
1604 {
1605 rPolygon[ 0 ] = maActPos;
1606 maActPos = rPolygon[ rPolygon.GetSize() - 1 ];
1607 }
1608 if ( bRecordPath )
1609 maPathObj.AddPolyLine( rPolygon );
1610 else
1611 {
1613 mpGDIMetaFile->AddAction( new MetaPolyLineAction( std::move(rPolygon), maLineStyle.aLineInfo ) );
1614 }
1615 }
1616
1617 void MtfTools::DrawPolyBezier( tools::Polygon rPolygon, bool bTo, bool bRecordPath )
1618 {
1619 sal_uInt16 nPoints = rPolygon.GetSize();
1620 if ( ( nPoints < 4 ) || ( ( ( nPoints - 4 ) % 3 ) != 0 ) )
1621 {
1622 SAL_WARN("emfio",
1623 "EMF file error: Number of Bezier points is not set of three");
1624 return;
1625 }
1627 ImplMap( rPolygon );
1628 if ( bTo )
1629 {
1630 rPolygon[ 0 ] = maActPos;
1631 maActPos = rPolygon[ nPoints - 1 ];
1632 }
1633 sal_uInt16 i;
1634 for ( i = 0; ( i + 2 ) < nPoints; )
1635 {
1636 rPolygon.SetFlags( i++, PolyFlags::Normal );
1637 rPolygon.SetFlags( i++, PolyFlags::Control );
1638 rPolygon.SetFlags( i++, PolyFlags::Control );
1639 }
1640 if ( bRecordPath )
1641 maPathObj.AddPolyLine( rPolygon );
1642 else
1643 {
1645 mpGDIMetaFile->AddAction( new MetaPolyLineAction( std::move(rPolygon), maLineStyle.aLineInfo ) );
1646 }
1647 }
1648
1649 void MtfTools::DrawText( Point& rPosition, OUString const & rText, KernArray* pDXArry, tools::Long* pDYArry, bool bRecordPath, GraphicsMode nGfxMode )
1650 {
1652 rPosition = ImplMap( rPosition );
1653 GraphicsMode nOldGfxMode = GetGfxMode();
1655
1656 if (pDXArry)
1657 {
1658 sal_Int64 nSumX = 0, nSumY = 0;
1659 for (sal_Int32 i = 0; i < rText.getLength(); i++ )
1660 {
1661 nSumX += (*pDXArry)[i];
1662
1663 // #i121382# Map DXArray using WorldTransform
1664 const Size aSizeX(ImplMap(Size(nSumX, 0)));
1665 const basegfx::B2DVector aVectorX(aSizeX.Width(), aSizeX.Height());
1666 pDXArry->set(i, basegfx::fround(aVectorX.getLength()) * (nSumX >= 0 ? 1 : -1));
1667
1668 if (pDYArry)
1669 {
1670 nSumY += pDYArry[i];
1671
1672 const Size aSizeY(ImplMap(Size(0, nSumY)));
1673 const basegfx::B2DVector aVectorY(aSizeY.Width(), aSizeY.Height());
1674 // Reverse Y
1675 pDYArry[i] = basegfx::fround(aVectorY.getLength());
1676 pDYArry[i] *= (nSumY >= 0 ? -1 : 1);
1677 }
1678 }
1679 }
1681 {
1684 }
1685 SetGfxMode(nGfxMode);
1686 TextAlign eTextAlign;
1688 eTextAlign = ALIGN_BASELINE;
1689 else if (mnTextAlign & TA_BOTTOM)
1690 eTextAlign = ALIGN_BOTTOM;
1691 else
1692 eTextAlign = ALIGN_TOP;
1693 bool bChangeFont = false;
1695 {
1696 bChangeFont = true;
1698 mpGDIMetaFile->AddAction( new MetaTextAlignAction( eTextAlign ) );
1699 }
1701 {
1702 bChangeFont = true;
1705 }
1706 bool bChangeFillColor = false;
1707 if ( maLatestBkColor != maBkColor )
1708 {
1709 bChangeFillColor = true;
1711 }
1712 if ( mnLatestBkMode != mnBkMode )
1713 {
1714 bChangeFillColor = true;
1716 }
1717 if ( bChangeFillColor )
1718 {
1719 bChangeFont = true;
1721 }
1722 vcl::Font aTmp( maFont );
1723 aTmp.SetColor( maTextColor );
1724 aTmp.SetFillColor( maBkColor );
1725
1727 aTmp.SetTransparent( true );
1728 else
1729 aTmp.SetTransparent( false );
1730
1731 aTmp.SetAlignment( eTextAlign );
1732
1733 if ( nGfxMode == GraphicsMode::GM_ADVANCED )
1734 {
1735 // check whether there is a font rotation applied via transformation
1736 Point aP1( ImplMap( Point() ) );
1737 Point aP2( ImplMap( Point( 0, 100 ) ) );
1738 aP2.AdjustX( -(aP1.X()) );
1739 aP2.AdjustY( -(aP1.Y()) );
1740 double fX = aP2.X();
1741 double fY = aP2.Y();
1742 if ( fX )
1743 {
1744 double fOrientation = basegfx::rad2deg(acos(fX / std::hypot(fX, fY)));
1745 if ( fY > 0 )
1746 fOrientation = 360 - fOrientation;
1747 fOrientation += 90;
1748 fOrientation *= 10;
1749 aTmp.SetOrientation( aTmp.GetOrientation() + Degree10( static_cast<sal_Int16>(fOrientation) ) );
1750 }
1751 }
1752
1754 {
1755 // #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
1756 SolarMutexGuard aGuard;
1758 sal_Int32 nTextWidth;
1759 Point aActPosDelta;
1760 pVDev->SetMapMode( MapMode( MapUnit::Map100thMM ) );
1761 pVDev->SetFont( maFont );
1762 const sal_uInt32 nLen = pDXArry ? rText.getLength() : 0;
1763 if (nLen)
1764 {
1765 nTextWidth = pVDev->GetTextWidth( OUString(rText[ nLen - 1 ]) );
1766 if( nLen > 1 )
1767 nTextWidth += (*pDXArry)[ nLen - 2 ];
1768 // tdf#39894: We should consider the distance to next character cell origin
1769 aActPosDelta.setX( (*pDXArry)[ nLen - 1 ] );
1770 if ( pDYArry )
1771 {
1772 aActPosDelta.setY( pDYArry[ nLen - 1 ] );
1773 }
1774 }
1775 else
1776 {
1777 nTextWidth = pVDev->GetTextWidth( rText );
1778 aActPosDelta.setX( nTextWidth );
1779 }
1780
1781 if( mnTextAlign & TA_UPDATECP )
1782 rPosition = maActPos;
1783
1785 {
1786 Point aDisplacement(((mnTextAlign & TA_RIGHT_CENTER) == TA_CENTER) ? nTextWidth >> 1: nTextWidth, 0);
1787 Point().RotateAround(aDisplacement, maFont.GetOrientation());
1788 rPosition -= aDisplacement;
1789 }
1790
1791 if( mnTextAlign & TA_UPDATECP )
1792 {
1793 Point().RotateAround(aActPosDelta, maFont.GetOrientation());
1794 maActPos = rPosition + aActPosDelta;
1795 }
1796 }
1797
1798 if(bChangeFont || (maLatestFont != aTmp))
1799 {
1800 maLatestFont = aTmp;
1801 rtl::Reference<MetaFontAction> aNewMetaFontAction(new MetaFontAction(aTmp));
1802
1803 // tdf#127471 end evtl active MetaFontAction scale corrector detector/collector
1805
1806 // !bRecordPath: else no MetaTextArrayAction will be created
1807 // nullptr != pDXArry: detection only possible when text size is given
1808 // rText.getLength(): no useful check without text
1809 if(!bRecordPath && nullptr != pDXArry && 0 != rText.getLength())
1810 {
1811 maScaledFontHelper.newCurrentMetaFontAction(aNewMetaFontAction);
1812 }
1813
1814 mpGDIMetaFile->AddAction( aNewMetaFontAction );
1818 }
1819
1820 if ( bRecordPath )
1821 {
1822 // TODO
1823 }
1824 else
1825 {
1826 if ( pDXArry && pDYArry )
1827 {
1828 for (sal_Int32 i = 0; i < rText.getLength(); ++i)
1829 {
1830 Point aCharDisplacement( i ? (*pDXArry)[i-1] : 0, i ? pDYArry[i-1] : 0 );
1831 Point().RotateAround(aCharDisplacement, maFont.GetOrientation());
1832 mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition + aCharDisplacement, OUString( rText[i] ), KernArraySpan(), {}, 0, 1 ) );
1833 }
1834 }
1835 else
1836 {
1837 /* because text without dx array is badly scaled, we
1838 will create such an array if necessary */
1839 KernArraySpan pDX;
1840 KernArray aMyDXArray;
1841 if (pDXArry)
1842 {
1843 pDX = *pDXArry;
1844 // only useful when we have an imported DXArray
1845 if(!rText.isEmpty())
1846 {
1848 rText,
1849 (*pDXArry)[rText.getLength() - 1] // extract imported TextLength
1850 );
1851 }
1852 }
1853 else
1854 {
1855 // #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
1856 SolarMutexGuard aGuard;
1858 pVDev->SetMapMode(MapMode(MapUnit::Map100thMM));
1859 pVDev->SetFont( maLatestFont );
1860 pVDev->GetTextArray( rText, &aMyDXArray, 0, rText.getLength());
1861 pDX = aMyDXArray;
1862 }
1863 mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, {}, 0, rText.getLength() ) );
1864 }
1865 }
1866 SetGfxMode( nOldGfxMode );
1867 }
1868
1869 void MtfTools::ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx& rBitmap )
1870 {
1871 BitmapEx aBmpEx( rBitmap );
1872 if ( mbComplexClip )
1873 {
1874 vcl::bitmap::DrawAndClipBitmap(rPos, rSize, rBitmap, aBmpEx, maClipPath.getClipPath());
1875 }
1876
1877 if ( aBmpEx.IsAlpha() )
1878 mpGDIMetaFile->AddAction( new MetaBmpExScaleAction( rPos, rSize, aBmpEx ) );
1879 else
1880 mpGDIMetaFile->AddAction( new MetaBmpScaleAction( rPos, rSize, aBmpEx.GetBitmap() ) );
1881 }
1882
1883 void MtfTools::ResolveBitmapActions( std::vector<BSaveStruct>& rSaveList )
1884 {
1886
1887 size_t nObjects = rSaveList.size();
1888 size_t nObjectsLeft = nObjects;
1889
1890 while ( nObjectsLeft )
1891 {
1892 size_t i;
1893 size_t nObjectsOfSameSize = 0;
1894 size_t nObjectStartIndex = nObjects - nObjectsLeft;
1895
1896 BSaveStruct* pSave = &rSaveList[nObjectStartIndex];
1897 tools::Rectangle aRect( pSave->aOutRect );
1898
1899 for ( i = nObjectStartIndex; i < nObjects; )
1900 {
1901 nObjectsOfSameSize++;
1902 if ( ++i < nObjects )
1903 {
1904 pSave = &rSaveList[i];
1905 if ( pSave->aOutRect != aRect )
1906 break;
1907 }
1908 }
1909 Point aPos( ImplMap( aRect.TopLeft() ) );
1910 Size aSize( ImplMap( aRect.GetSize() ) );
1911
1912 for ( i = nObjectStartIndex; i < ( nObjectStartIndex + nObjectsOfSameSize ); i++ )
1913 {
1914 pSave = &rSaveList[i];
1915
1916 sal_uInt32 nWinRop = pSave->nWinRop;
1917 sal_uInt8 nRasterOperation = static_cast<sal_uInt8>( nWinRop >> 16 );
1918
1919 sal_uInt32 nUsed = 0;
1920 if ( ( nRasterOperation & 0xf ) != ( nRasterOperation >> 4 ) )
1921 nUsed |= 1; // pattern is used
1922 if ( ( nRasterOperation & 0x33 ) != ( ( nRasterOperation & 0xcc ) >> 2 ) )
1923 nUsed |= 2; // source is used
1924 if ( ( nRasterOperation & 0xaa ) != ( ( nRasterOperation & 0x55 ) << 1 ) )
1925 nUsed |= 4; // destination is used
1926
1927 if ( (nUsed & 1) && (( nUsed & 2 ) == 0) && nWinRop != PATINVERT )
1928 { // patterns aren't well supported yet
1929 WMFRasterOp nOldRop = SetRasterOp( WMFRasterOp::NONE ); // in this case nRasterOperation is either 0 or 0xff
1931 DrawRect( aRect, false );
1932 SetRasterOp( nOldRop );
1933 }
1934 else
1935 {
1936 bool bDrawn = false;
1937
1938 if ( i == nObjectStartIndex ) // optimizing, sometimes it is possible to create just one transparent bitmap
1939 {
1940 if ( nObjectsOfSameSize == 2 )
1941 {
1942 BSaveStruct* pSave2 = &rSaveList[i + 1];
1943 if ( ( pSave->aBmpEx.GetPrefSize() == pSave2->aBmpEx.GetPrefSize() ) &&
1944 ( pSave->aBmpEx.GetPrefMapMode() == pSave2->aBmpEx.GetPrefMapMode() ) )
1945 {
1946 // TODO: Strictly speaking, we should
1947 // check whether mask is monochrome, and
1948 // whether image is black (upper branch)
1949 // or white (lower branch). Otherwise, the
1950 // effect is not the same as a masked
1951 // bitmap.
1952 if ( ( nWinRop == SRCPAINT ) && ( pSave2->nWinRop == SRCAND ) )
1953 {
1954 Bitmap aMask( pSave->aBmpEx.GetBitmap() ); aMask.Invert();
1955 BitmapEx aBmpEx( pSave2->aBmpEx.GetBitmap(), aMask );
1956 ImplDrawBitmap( aPos, aSize, aBmpEx );
1957 bDrawn = true;
1958 i++;
1959 }
1960 // #i20085# This is just the other way
1961 // around as above. Only difference: mask
1962 // is inverted
1963 else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCPAINT ) )
1964 {
1965 const Bitmap & rMask( pSave->aBmpEx.GetBitmap() );
1966 BitmapEx aBmpEx( pSave2->aBmpEx.GetBitmap(), rMask );
1967 ImplDrawBitmap( aPos, aSize, aBmpEx );
1968 bDrawn = true;
1969 i++;
1970 }
1971 // tdf#90539
1972 else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCINVERT ) )
1973 {
1974 const Bitmap & rMask( pSave->aBmpEx.GetBitmap() );
1975 BitmapEx aBmpEx( pSave2->aBmpEx.GetBitmap(), rMask );
1976 ImplDrawBitmap( aPos, aSize, aBmpEx );
1977 bDrawn = true;
1978 i++;
1979 }
1980 }
1981 }
1982 }
1983
1984 if ( !bDrawn )
1985 {
1986 Push();
1988 Bitmap aBitmap( pSave->aBmpEx.GetBitmap() );
1989 sal_uInt32 nOperation = ( nRasterOperation & 0xf );
1990 switch( nOperation )
1991 {
1992 case 0x1 :
1993 case 0xe :
1994 {
1995 if(pSave->aBmpEx.IsAlpha())
1996 {
1997 ImplDrawBitmap( aPos, aSize, pSave->aBmpEx );
1998 }
1999 else
2000 {
2002 ImplDrawBitmap( aPos, aSize, BitmapEx(aBitmap) );
2004 Bitmap aMask( aBitmap );
2005 aMask.Invert();
2006 BitmapEx aBmpEx( aBitmap, aMask );
2007 ImplDrawBitmap( aPos, aSize, aBmpEx );
2008 if ( nOperation == 0x1 )
2009 {
2011 DrawRect( aRect, false );
2012 }
2013 }
2014 }
2015 break;
2016 case 0x7 :
2017 case 0x8 :
2018 {
2019 Bitmap aMask( aBitmap );
2020 if ( ( nUsed & 1 ) && ( nRasterOperation & 0xb0 ) == 0xb0 ) // pattern used
2021 {
2022 aBitmap.Convert( BmpConversion::N24Bit );
2023 aBitmap.Erase( maFillStyle.aFillColor );
2024 }
2025 BitmapEx aBmpEx( aBitmap, aMask );
2026 ImplDrawBitmap( aPos, aSize, aBmpEx );
2027 if ( nOperation == 0x7 )
2028 {
2030 DrawRect( aRect, false );
2031 }
2032 }
2033 break;
2034
2035 case 0x4 :
2036 case 0xb :
2037 {
2039 DrawRect( aRect, false );
2041 Bitmap aMask( aBitmap );
2042 aBitmap.Invert();
2043 BitmapEx aBmpEx( aBitmap, aMask );
2044 ImplDrawBitmap( aPos, aSize, aBmpEx );
2046 ImplDrawBitmap( aPos, aSize, BitmapEx(aBitmap) );
2047 if ( nOperation == 0xb )
2048 {
2050 DrawRect( aRect, false );
2051 }
2052 }
2053 break;
2054
2055 case 0x2 :
2056 case 0xd :
2057 {
2058 Bitmap aMask( aBitmap );
2059 aMask.Invert();
2060 BitmapEx aBmpEx( aBitmap, aMask );
2061 ImplDrawBitmap( aPos, aSize, aBmpEx );
2063 ImplDrawBitmap( aPos, aSize, BitmapEx(aBitmap) );
2064 if ( nOperation == 0xd )
2065 {
2067 DrawRect( aRect, false );
2068 }
2069 }
2070 break;
2071 case 0x6 :
2072 case 0x9 :
2073 {
2075 ImplDrawBitmap( aPos, aSize, BitmapEx(aBitmap) );
2076 if ( nOperation == 0x9 )
2077 {
2079 DrawRect( aRect, false );
2080 }
2081 }
2082 break;
2083
2084 case 0x0 : // WHITENESS
2085 case 0xf : // BLACKNESS
2086 { // in this case nRasterOperation is either 0 or 0xff
2087 maFillStyle = WinMtfFillStyle( Color( nRasterOperation, nRasterOperation, nRasterOperation ) );
2089 DrawRect( aRect, false );
2090 }
2091 break;
2092
2093 case 0x3 : // only source is used
2094 case 0xc :
2095 {
2096 if ( nRasterOperation == 0x33 )
2097 aBitmap.Invert();
2098 if (pSave->m_bForceAlpha)
2099 {
2100 ImplDrawBitmap(aPos, aSize, pSave->aBmpEx);
2101 }
2102 else
2103 {
2104 ImplDrawBitmap(aPos, aSize, BitmapEx(aBitmap));
2105 }
2106 }
2107 break;
2108
2109 case 0x5 : // only destination is used
2110 {
2112 DrawRect( aRect, false );
2113 }
2114 break;
2115
2116 case 0xa : // no operation
2117 break;
2118 }
2119 SetRasterOp( nOldRop );
2120 Pop();
2121 }
2122 }
2123 }
2124 nObjectsLeft -= nObjectsOfSameSize;
2125 }
2126
2127 rSaveList.clear();
2128 }
2129
2130 void MtfTools::SetDevOrg( const Point& rPoint )
2131 {
2132 mnDevOrgX = rPoint.X();
2133 mnDevOrgY = rPoint.Y();
2134 }
2135
2136 void MtfTools::SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
2137 {
2138 mnDevOrgX += nXAdd;
2139 mnDevOrgY += nYAdd;
2140 }
2141
2142 void MtfTools::SetDevExt( const Size& rSize ,bool regular)
2143 {
2144 if ( !(rSize.Width() && rSize.Height()) )
2145 return;
2146
2147 switch( meMapMode )
2148 {
2150 case MappingMode::MM_ANISOTROPIC :
2151 {
2152 mnDevWidth = rSize.Width();
2153 mnDevHeight = rSize.Height();
2154 break;
2155 }
2156
2157 //do nothing
2158 default:
2159 break;
2160 }
2161 if (regular)
2162 {
2163 mbIsMapDevSet=true;
2164 }
2165 }
2166
2167 void MtfTools::ScaleDevExt(double fX, double fY)
2168 {
2171 }
2172
2173 void MtfTools::SetWinOrg( const Point& rPoint , bool bIsEMF)
2174 {
2175 mnWinOrgX = rPoint.X();
2176 mnWinOrgY = rPoint.Y();
2177 if (bIsEMF)
2178 {
2179 SetDevByWin();
2180 }
2181 mbIsMapWinSet=true;
2182 }
2183
2184 void MtfTools::SetWinOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
2185 {
2186 mnWinOrgX += nXAdd;
2187 mnWinOrgY += nYAdd;
2188 }
2189
2190 void MtfTools::SetDevByWin() //mnWinExt...-stuff has to be assigned before.
2191 {
2192 if (!mbIsMapDevSet)
2193 {
2194 if ( meMapMode == MappingMode::MM_ISOTROPIC ) //TODO: WHAT ABOUT ANISOTROPIC???
2195 {
2196 sal_Int32 nX, nY;
2198 return;
2200 SetDevExt(aSize, false);
2201 }
2202 }
2203 }
2204
2205 void MtfTools::SetWinExt(const Size& rSize, bool bIsEMF)
2206 {
2207 if (!(rSize.Width() && rSize.Height()))
2208 return;
2209
2210 switch( meMapMode )
2211 {
2213 case MappingMode::MM_ANISOTROPIC :
2214 {
2215 mnWinExtX = rSize.Width();
2216 mnWinExtY = rSize.Height();
2217 if (bIsEMF)
2218 {
2219 SetDevByWin();
2220 }
2221 mbIsMapWinSet = true;
2222 break;
2223 }
2224
2225 default:
2226 //do nothing
2227 break;
2228 }
2229 }
2230
2231 void MtfTools::ScaleWinExt(double fX, double fY)
2232 {
2235 }
2236
2238 {
2239 mrclBounds = rRect;
2240 }
2241
2243 {
2244 mrclFrame = rRect;
2245 }
2246
2247 void MtfTools::SetRefPix( const Size& rSize )
2248 {
2249 mnPixX = rSize.Width();
2250 mnPixY = rSize.Height();
2251 }
2252
2253 void MtfTools::SetRefMill( const Size& rSize )
2254 {
2255 mnMillX = rSize.Width();
2256 mnMillY = rSize.Height();
2257 }
2258
2260 {
2261 meMapMode = nMapMode;
2262 if ( nMapMode == MappingMode::MM_TEXT && !mbIsMapWinSet )
2263 {
2266 }
2267 else if ( meMapMode == MappingMode::MM_HIMETRIC )
2268 {
2269 sal_Int32 nWinExtX, nWinExtY;
2270 if (o3tl::checked_multiply<sal_Int32>(mnMillX, 100, nWinExtX) ||
2271 o3tl::checked_multiply<sal_Int32>(mnMillY, 100, nWinExtY))
2272 {
2273 return;
2274 }
2275 mnWinExtX = nWinExtX;
2276 mnWinExtY = nWinExtY;
2277 }
2278 }
2279
2281 {
2282 maXForm.eM11 = rXForm.eM11;
2283 maXForm.eM12 = rXForm.eM12;
2284 maXForm.eM21 = rXForm.eM21;
2285 maXForm.eM22 = rXForm.eM22;
2286 maXForm.eDx = rXForm.eDx;
2287 maXForm.eDy = rXForm.eDy;
2288 }
2289
2291 {
2292 switch( nMode )
2293 {
2295 {
2296 maXForm.eM11 = maXForm.eM22 = 1.0f;
2298 break;
2299 }
2300
2303 {
2304 const XForm* pLeft;
2305 const XForm* pRight;
2306
2308 {
2309 pLeft = &rXForm;
2310 pRight = &maXForm;
2311 }
2312 else
2313 {
2314 pLeft = &maXForm;
2315 pRight = &rXForm;
2316 }
2317
2318 float aF[3][3];
2319 float bF[3][3];
2320 float cF[3][3];
2321
2322 aF[0][0] = pLeft->eM11;
2323 aF[0][1] = pLeft->eM12;
2324 aF[0][2] = 0;
2325 aF[1][0] = pLeft->eM21;
2326 aF[1][1] = pLeft->eM22;
2327 aF[1][2] = 0;
2328 aF[2][0] = pLeft->eDx;
2329 aF[2][1] = pLeft->eDy;
2330 aF[2][2] = 1;
2331
2332 bF[0][0] = pRight->eM11;
2333 bF[0][1] = pRight->eM12;
2334 bF[0][2] = 0;
2335 bF[1][0] = pRight->eM21;
2336 bF[1][1] = pRight->eM22;
2337 bF[1][2] = 0;
2338 bF[2][0] = pRight->eDx;
2339 bF[2][1] = pRight->eDy;
2340 bF[2][2] = 1;
2341
2342 int i, j, k;
2343 for ( i = 0; i < 3; i++ )
2344 {
2345 for ( j = 0; j < 3; j++ )
2346 {
2347 cF[i][j] = 0;
2348 for ( k = 0; k < 3; k++ )
2349 cF[i][j] += aF[i][k] * bF[k][j];
2350 }
2351 }
2352 maXForm.eM11 = cF[0][0];
2353 maXForm.eM12 = cF[0][1];
2354 maXForm.eM21 = cF[1][0];
2355 maXForm.eM22 = cF[1][1];
2356 maXForm.eDx = cF[2][0];
2357 maXForm.eDy = cF[2][1];
2358 break;
2359 }
2361 {
2362 SetWorldTransform(rXForm);
2363 break;
2364 }
2365 }
2366 }
2367
2368 void MtfTools::Push() // !! to be able to access the original ClipRegion it
2369 { // is not allowed to use the MetaPushAction()
2370 UpdateClipRegion(); // (the original clip region is on top of the stack) (SJ)
2371 auto pSave = std::make_shared<SaveStruct>();
2372
2373 pSave->aLineStyle = maLineStyle;
2374 pSave->aFillStyle = maFillStyle;
2375
2376 pSave->aFont = maFont;
2377 pSave->aTextColor = maTextColor;
2378 pSave->nTextAlign = mnTextAlign;
2379 pSave->nTextLayoutMode = mnTextLayoutMode;
2380 pSave->eMapMode = meMapMode;
2381 pSave->eGfxMode = meGfxMode;
2382 pSave->nBkMode = mnBkMode;
2383 pSave->aBkColor = maBkColor;
2384 pSave->bClockWiseArcDirection = mbClockWiseArcDirection;
2385 pSave->bFillStyleSelected = mbFillStyleSelected;
2386
2387 pSave->aActPos = maActPos;
2388 pSave->aXForm = maXForm;
2389 pSave->eRasterOp = meRasterOp;
2390
2391 pSave->nWinOrgX = mnWinOrgX;
2392 pSave->nWinOrgY = mnWinOrgY;
2393 pSave->nWinExtX = mnWinExtX;
2394 pSave->nWinExtY = mnWinExtY;
2395 pSave->nDevOrgX = mnDevOrgX;
2396 pSave->nDevOrgY = mnDevOrgY;
2397 pSave->nDevWidth = mnDevWidth;
2398 pSave->nDevHeight = mnDevHeight;
2399
2400 pSave->maPathObj = maPathObj;
2401 pSave->maClipPath = maClipPath;
2402
2403 SAL_INFO("emfio", "\t\t GfxMode: " << static_cast<sal_uInt32>(meGfxMode));
2404 SAL_INFO("emfio", "\t\t MapMode: " << static_cast<sal_uInt32>(meMapMode));
2405 SAL_INFO("emfio", "\t\t WinOrg: " << mnWinOrgX << ", " << mnWinOrgY);
2406 SAL_INFO("emfio", "\t\t WinExt: " << mnWinExtX << " x " << mnWinExtY);
2407 SAL_INFO("emfio", "\t\t DevOrg: " << mnDevOrgX << ", " << mnDevOrgY);
2408 SAL_INFO("emfio", "\t\t DevWidth/Height: " << mnDevWidth << " x " << mnDevHeight);
2409 SAL_INFO("emfio", "\t\t LineStyle: " << maLineStyle.aLineColor << " FillStyle: " << maFillStyle.aFillColor );
2410 mvSaveStack.push_back( pSave );
2411 }
2412
2413 void MtfTools::Pop( const sal_Int32 nSavedDC )
2414 {
2415 if ( nSavedDC == 0 )
2416 return;
2417
2418 sal_Int32 aIndex;
2419 if ( nSavedDC < 0 ) // WMF/EMF, if negative, nSavedDC represents an instance relative to the current state.
2420 aIndex = static_cast< sal_Int32 >( mvSaveStack.size() ) + nSavedDC;
2421 else
2422 aIndex = nSavedDC; // WMF, if positive, nSavedDC represents a specific instance of the state to be restored.
2423 if( aIndex < 0 )
2424 {
2425 mvSaveStack.clear();
2426 return;
2427 }
2428 if( mvSaveStack.empty() || ( aIndex >= static_cast< sal_Int32 >( mvSaveStack.size() ) ) )
2429 return;
2430
2431 mvSaveStack.resize( aIndex + 1 );
2432 // Backup the current data on the stack
2433 std::shared_ptr<SaveStruct>& pSave( mvSaveStack.back() );
2434
2435 maLineStyle = pSave->aLineStyle;
2436 maFillStyle = pSave->aFillStyle;
2437
2438 maFont = pSave->aFont;
2439 maTextColor = pSave->aTextColor;
2440 mnTextAlign = pSave->nTextAlign;
2441 mnTextLayoutMode = pSave->nTextLayoutMode;
2442 mnBkMode = pSave->nBkMode;
2443 meGfxMode = pSave->eGfxMode;
2444 meMapMode = pSave->eMapMode;
2445 maBkColor = pSave->aBkColor;
2446 mbClockWiseArcDirection = pSave->bClockWiseArcDirection;
2447 mbFillStyleSelected = pSave->bFillStyleSelected;
2448
2449 maActPos = pSave->aActPos;
2450 maXForm = pSave->aXForm;
2451 meRasterOp = pSave->eRasterOp;
2452
2453 mnWinOrgX = pSave->nWinOrgX;
2454 mnWinOrgY = pSave->nWinOrgY;
2455 mnWinExtX = pSave->nWinExtX;
2456 mnWinExtY = pSave->nWinExtY;
2457 mnDevOrgX = pSave->nDevOrgX;
2458 mnDevOrgY = pSave->nDevOrgY;
2459 mnDevWidth = pSave->nDevWidth;
2460 mnDevHeight = pSave->nDevHeight;
2461
2462 maPathObj = pSave->maPathObj;
2463 if ( ! ( maClipPath == pSave->maClipPath ) )
2464 {
2465 maClipPath = pSave->maClipPath;
2466 mbClipNeedsUpdate = true;
2467 }
2469 {
2472 }
2473
2474 SAL_INFO("emfio", "\t\t GfxMode: " << static_cast<sal_uInt32>(meGfxMode));
2475 SAL_INFO("emfio", "\t\t MapMode: " << static_cast<sal_uInt32>(meMapMode));
2476 SAL_INFO("emfio", "\t\t WinOrg: " << mnWinOrgX << ", " << mnWinOrgY);
2477 SAL_INFO("emfio", "\t\t WinExt: " << mnWinExtX << " x " << mnWinExtY);
2478 SAL_INFO("emfio", "\t\t DevOrg: " << mnDevOrgX << ", " << mnDevOrgY);
2479 SAL_INFO("emfio", "\t\t DevWidth/Height: " << mnDevWidth << " x " << mnDevHeight);
2480 SAL_INFO("emfio", "\t\t LineStyle: " << maLineStyle.aLineColor << " FillStyle: " << maFillStyle.aFillColor );
2481 mvSaveStack.pop_back();
2482 }
2483
2485 {
2486 rGDIMetaFile.Play( *mpGDIMetaFile );
2487 }
2488
2490 {
2491 EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS header info\n"));
2492
2493 SvMemoryStream mem;
2494 sal_Int32 nLeft, nRight, nTop, nBottom;
2495
2496 nLeft = mrclFrame.Left();
2497 nTop = mrclFrame.Top();
2498 nRight = mrclFrame.Right();
2499 nBottom = mrclFrame.Bottom();
2500
2501 // emf header info
2502 mem.WriteInt32( nLeft ).WriteInt32( nTop ).WriteInt32( nRight ).WriteInt32( nBottom );
2504
2505 float one, zero;
2506
2507 one = 1;
2508 zero = 0;
2509
2510 // add transformation matrix to be used in vcl's metaact.cxx for
2511 // rotate and scale operations
2512 mem.WriteFloat( one ).WriteFloat( zero ).WriteFloat( zero ).WriteFloat( one ).WriteFloat( zero ).WriteFloat( zero );
2513
2514 // need to flush the stream, otherwise GetEndOfData will return 0
2515 // on windows where the function parameters are probably resolved in reverse order
2516 mem.Flush();
2517
2518 mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS_HEADER_INFO", 0, static_cast<const sal_uInt8*>(mem.GetData()), mem.GetEndOfData() ) );
2519 mpGDIMetaFile->UseCanvas( true );
2520 }
2521
2522 void MtfTools::PassEMFPlus( void const * pBuffer, sal_uInt32 nLength )
2523 {
2524 EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS comment length %04x\n",(unsigned int) nLength));
2525 mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS", 0, static_cast<const sal_uInt8*>(pBuffer), nLength ) );
2526 }
2527}
2528
2529/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
RasterOp
bool IsAlpha() const
Bitmap GetBitmap(Color aTransparentReplaceColor) const
const MapMode & GetPrefMapMode() const
const Size & GetPrefSize() const
bool Convert(BmpConversion eConversion)
bool Invert()
bool Erase(const Color &rFillColor)
tools::Long GetDescent() const
tools::Long GetAscent() const
void AddAction(const rtl::Reference< MetaAction > &pAction)
void UseCanvas(bool _bUseCanvas)
void Play(GDIMetaFile &rMtf)
void SetPrefMapMode(const MapMode &rMapMode)
void SetPrefSize(const Size &rSize)
void set(size_t nIndex, sal_Int32 nValue)
LineStyle GetStyle() const
double GetWidth() const
constexpr tools::Long Y() const
void setX(tools::Long nX)
void RotateAround(tools::Long &rX, tools::Long &rY, Degree10 nOrientation) const
void setY(tools::Long nY)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
constexpr tools::Long Height() const
tools::Long AdjustWidth(tools::Long n)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
void SetSynchronMode(bool bTheSync=true)
const void * GetData()
std::size_t GetEndOfData() const
virtual sal_uInt64 TellEnd() override
SvStream & WriteInt32(sal_Int32 nInt32)
sal_uInt64 Tell() const
SvStream & ReadFloat(float &rFloat)
SvStream & WriteFloat(float nFloat)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
SvLockBytes * GetLockBytes() const
void Flush()
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
void translate(double fX, double fY)
B2DRange getB2DRange() const
sal_uInt32 count() const
double getLength() const
TYPE getX() const
void setY(TYPE fY)
TYPE getY() const
void setX(TYPE fX)
void intersectPolyPolygon(const B2DPolyPolygon &)
void subtractPolyPolygon(const B2DPolyPolygon &)
void unionPolyPolygon(const B2DPolyPolygon &)
void transform(const B2DHomMatrix &)
B2DPolyPolygon const & getClipPoly() const
void xorPolyPolygon(const B2DPolyPolygon &)
void AddFromGDIMetaFile(GDIMetaFile &rGDIMetaFile)
Definition: mtftools.cxx:2484
WMFRasterOp mnRop
Definition: mtftools.hxx:667
void DrawChord(const tools::Rectangle &rRect, const Point &rStartAngle, const Point &rEndAngle)
Definition: mtftools.cxx:1465
void PassEMFPlus(void const *pBuffer, sal_uInt32 nLength)
Definition: mtftools.cxx:2522
MappingMode meMapMode
Definition: mtftools.hxx:671
Point ImplScale(const Point &rPt)
Definition: mtftools.cxx:501
void DrawPolygon(tools::Polygon rPolygon, bool bRecordPath)
Definition: mtftools.cxx:1488
void CreateObject()
Definition: mtftools.cxx:991
WinMtfFillStyle maLatestFillStyle
Definition: mtftools.hxx:645
WinMtfFillStyle maFillStyle
Definition: mtftools.hxx:646
Color ReadColor()
Definition: mtftools.cxx:481
void SetMapMode(MappingMode mnMapMode)
Definition: mtftools.cxx:2259
GraphicsMode GetGfxMode() const
Definition: mtftools.hxx:757
void ScaleDevExt(double fX, double fY)
Definition: mtftools.cxx:2167
void LineTo(const Point &rPoint, bool bRecordPath=false)
Definition: mtftools.cxx:1308
GDIMetaFile * mpGDIMetaFile
Definition: mtftools.hxx:690
vcl::Font maFont
Definition: mtftools.hxx:651
WinMtfClipPath maClipPath
Definition: mtftools.hxx:640
WinMtfPalette maPalette
Definition: mtftools.hxx:648
void ScaleWinExt(double fX, double fY)
Definition: mtftools.cxx:2231
void SetArcDirection(bool bCounterClockWise)
Definition: mtftools.cxx:862
void SetDevOrg(const Point &rPoint)
Definition: mtftools.cxx:2130
WMFRasterOp SetRasterOp(WMFRasterOp nRasterOp)
Definition: mtftools.cxx:1205
void UpdateClipRegion()
Definition: mtftools.cxx:1137
void SetWinExt(const Size &rSize, bool bIsEMF=false)
Definition: mtftools.cxx:2205
sal_Int32 mnWinExtY
Definition: mtftools.hxx:681
sal_Int32 mnDevOrgX
Definition: mtftools.hxx:674
void DrawEllipse(const tools::Rectangle &rRect)
Definition: mtftools.cxx:1391
void SetTextAlign(sal_uInt32 nAlign)
Definition: mtftools.cxx:883
void SetWorldTransform(const XForm &rXForm)
Definition: mtftools.cxx:2280
GraphicsMode meGfxMode
Definition: mtftools.hxx:670
void DrawPolyLine(tools::Polygon rPolygon, bool bDrawTo=false, bool bRecordPath=false)
Definition: mtftools.cxx:1594
sal_Int32 mnMillX
Definition: mtftools.hxx:685
void ImplResizeObjectArry(sal_uInt32 nNewEntry)
Definition: mtftools.cxx:888
void SetClipPath(const tools::PolyPolygon &rPolyPoly, RegionMode nClippingMode, bool bIsMapped)
Definition: mtftools.cxx:1039
void SetrclBounds(const tools::Rectangle &rRect)
Definition: mtftools.cxx:2237
WinMtfLineStyle maLineStyle
Definition: mtftools.hxx:643
void UpdateFillStyle()
Definition: mtftools.cxx:1193
void StrokeAndFillPath(bool bStroke, bool bFill)
Definition: mtftools.cxx:1252
sal_Int32 mnDevWidth
Definition: mtftools.hxx:676
void IntersectClipRect(const tools::Rectangle &rRect)
Definition: mtftools.cxx:1007
vcl::text::ComplexTextLayoutFlags mnTextLayoutMode
Definition: mtftools.hxx:659
void CreateObjectIndexed(sal_uInt32 nIndex, std::unique_ptr< GDIObj > pObject)
Definition: mtftools.cxx:954
Color maLatestBkColor
Definition: mtftools.hxx:656
void SetDefaultClipPath()
Definition: mtftools.cxx:1056
void PassEMFPlusHeaderInfo()
Definition: mtftools.cxx:2489
bool mbFillStyleSelected
Definition: mtftools.hxx:702
void SetDevExt(const Size &rSize, bool regular=true)
Definition: mtftools.cxx:2142
void UpdateLineStyle()
Definition: mtftools.cxx:1184
std::vector< std::unique_ptr< GDIObj > > mvGDIObj
Definition: mtftools.hxx:665
BackgroundMode mnBkMode
Definition: mtftools.hxx:661
sal_Int32 mnPixY
Definition: mtftools.hxx:684
sal_Int32 mnDevHeight
Definition: mtftools.hxx:677
void SetrclFrame(const tools::Rectangle &rRect)
Definition: mtftools.cxx:2242
void ResolveBitmapActions(std::vector< BSaveStruct > &rSaveList)
Definition: mtftools.cxx:1883
bool mbClipNeedsUpdate
Definition: mtftools.hxx:703
SvStream * mpInputStream
Definition: mtftools.hxx:692
void SetRefMill(const Size &rSize)
Definition: mtftools.cxx:2253
sal_Int32 mnWinOrgX
Definition: mtftools.hxx:678
void SetWinOrgOffset(sal_Int32 nX, sal_Int32 nY)
Definition: mtftools.cxx:2184
void DrawPie(const tools::Rectangle &rRect, const Point &rStartAngle, const Point &rEndAngle)
Definition: mtftools.cxx:1442
void SetWinOrg(const Point &rPoint, bool bIsEMF=false)
Definition: mtftools.cxx:2173
sal_Int32 mnMillY
Definition: mtftools.hxx:686
void ClearPath()
Definition: mtftools.hxx:773
void MoveTo(const Point &rPoint, bool bRecordPath=false)
Definition: mtftools.cxx:1294
void ModifyWorldTransform(const XForm &rXForm, ModifyWorldTransformMode nMode)
Definition: mtftools.cxx:2290
tools::Rectangle mrclFrame
Definition: mtftools.hxx:687
void DrawPolyPolygon(tools::PolyPolygon &rPolyPolygon, bool bRecordPath=false)
Definition: mtftools.cxx:1561
void DrawText(Point &rPosition, OUString const &rString, KernArray *pDXArry=nullptr, tools::Long *pDYArry=nullptr, bool bRecordPath=false, GraphicsMode nGraphicsMode=GraphicsMode::GM_COMPATIBLE)
Definition: mtftools.cxx:1649
~MtfTools() COVERITY_NOEXCEPT_FALSE
Definition: mtftools.cxx:1127
vcl::Font maLatestFont
Definition: mtftools.hxx:650
sal_uInt32 mnStartPos
Definition: mtftools.hxx:693
void ImplSetNonPersistentLineColorTransparenz()
Definition: mtftools.cxx:1174
bool mbClockWiseArcDirection
Definition: mtftools.hxx:701
void SetBkColor(const Color &rColor)
Definition: mtftools.cxx:873
WinMtfPathObj maPathObj
Definition: mtftools.hxx:639
vcl::text::ComplexTextLayoutFlags mnLatestTextLayoutMode
Definition: mtftools.hxx:658
RasterOp meLatestRasterOp
Definition: mtftools.hxx:662
Color maLatestTextColor
Definition: mtftools.hxx:654
void DeleteObject(sal_uInt32 nIndex)
Definition: mtftools.cxx:996
void Pop(const sal_Int32 nSavedDC=-1)
Definition: mtftools.cxx:2413
void ImplDrawClippedPolyPolygon(const tools::PolyPolygon &rPolyPoly)
Definition: mtftools.cxx:893
void DrawRectWithBGColor(const tools::Rectangle &rRect)
Definition: mtftools.cxx:1322
ScaledFontDetectCorrectHelper maScaledFontHelper
Definition: mtftools.hxx:698
void SetTextLayoutMode(vcl::text::ComplexTextLayoutFlags nLayoutMode)
Definition: mtftools.cxx:857
sal_Int32 mnDevOrgY
Definition: mtftools.hxx:675
sal_uInt32 mnLatestTextAlign
Definition: mtftools.hxx:652
void SetGfxMode(GraphicsMode nGfxMode)
Definition: mtftools.hxx:756
void DrawRect(const tools::Rectangle &rRect, bool bEdge=true)
Definition: mtftools.cxx:1339
void DrawRoundRect(const tools::Rectangle &rRect, const Size &rSize)
Definition: mtftools.cxx:1377
WinMtfFillStyle maNopFillStyle
Definition: mtftools.hxx:647
void ImplDrawBitmap(const Point &rPos, const Size &rSize, const BitmapEx &rBitmap)
Definition: mtftools.cxx:1869
void DrawArc(const tools::Rectangle &rRect, const Point &rStartAngle, const Point &rEndAngle, bool bDrawTo=false)
Definition: mtftools.cxx:1413
RasterOp meRasterOp
Definition: mtftools.hxx:663
void SelectObject(sal_uInt32 nIndex)
Definition: mtftools.cxx:748
sal_Int32 mnWinOrgY
Definition: mtftools.hxx:679
MtfTools(MtfTools const &)=delete
sal_uInt32 mnTextAlign
Definition: mtftools.hxx:653
void SetBkMode(BackgroundMode nMode)
Definition: mtftools.cxx:868
sal_Int32 mnWinExtX
Definition: mtftools.hxx:680
void DrawPolyBezier(tools::Polygon rPolygon, bool bDrawTo, bool bRecordPath)
Definition: mtftools.cxx:1617
void SetDevOrgOffset(sal_Int32 nXAdd, sal_Int32 nYAdd)
Definition: mtftools.cxx:2136
void SetRefPix(const Size &rSize)
Definition: mtftools.cxx:2247
WinMtfLineStyle maLatestLineStyle
Definition: mtftools.hxx:642
std::vector< std::shared_ptr< SaveStruct > > mvSaveStack
Definition: mtftools.hxx:668
tools::Rectangle mrclBounds
Definition: mtftools.hxx:688
Point ImplMap(const Point &rPt)
Definition: mtftools.cxx:510
BackgroundMode mnLatestBkMode
Definition: mtftools.hxx:660
sal_Int32 mnPixX
Definition: mtftools.hxx:683
void SetTextColor(const Color &rColor)
Definition: mtftools.cxx:878
void SetDevByWin()
Definition: mtftools.cxx:2190
void ExcludeClipRect(const tools::Rectangle &rRect)
Definition: mtftools.cxx:1021
void MoveClipRegion(const Size &rSize)
Definition: mtftools.cxx:1031
WinMtfLineStyle maNopLineStyle
Definition: mtftools.hxx:644
void DrawPixel(const Point &rSource, const Color &rColor)
Definition: mtftools.cxx:1289
rtl::Reference< MetaFontAction > maCurrentMetaFontAction
Definition: mtftools.hxx:620
void evaluateAlternativeFontScale(OUString const &rText, tools::Long nImportedTextLength)
Definition: mtftools.cxx:374
std::vector< double > maAlternativeFontScales
Definition: mtftools.hxx:621
std::vector< std::pair< rtl::Reference< MetaFontAction >, double > > maPositiveIdentifiedCases
Definition: mtftools.hxx:622
std::vector< std::pair< rtl::Reference< MetaFontAction >, double > > maNegativeIdentifiedCases
Definition: mtftools.hxx:623
void newCurrentMetaFontAction(const rtl::Reference< MetaFontAction > &rNewMetaFontAction)
Definition: mtftools.cxx:349
void setClipPath(const basegfx::B2DPolyPolygon &, RegionMode nClippingMode)
Definition: mtftools.cxx:79
basegfx::B2DPolyPolygon const & getClipPath() const
Definition: mtftools.cxx:114
void excludeClip(const basegfx::B2DPolyPolygon &rPolyPolygon)
Definition: mtftools.cxx:74
void intersectClip(const basegfx::B2DPolyPolygon &rPolyPolygon)
Definition: mtftools.cxx:69
bool isEmpty() const
Definition: mtftools.hxx:348
basegfx::utils::B2DClipState const & getClip() const
Definition: mtftools.hxx:350
basegfx::utils::B2DClipState maClip
Definition: mtftools.hxx:337
void moveClipRegion(const Size &rSize)
Definition: mtftools.cxx:101
void AddPolyPolygon(const tools::PolyPolygon &rPolyPolygon)
Definition: mtftools.cxx:143
void AddPolyLine(const tools::Polygon &rPoly)
Definition: mtftools.cxx:128
void AddPoint(const Point &rPoint)
Definition: mtftools.cxx:119
void AddPolygon(const tools::Polygon &rPoly)
Definition: mtftools.cxx:137
sal_uInt16 Count() const
void GetIntersection(const tools::PolyPolygon &rPolyPoly, tools::PolyPolygon &rResult) const
::basegfx::B2DPolyPolygon getB2DPolyPolygon() const
bool IsRect() const
void Insert(const tools::Polygon &rPoly, sal_uInt16 nPos=POLYPOLY_APPEND)
const tools::Polygon & GetObject(sal_uInt16 nPos) const
tools::Rectangle GetBoundRect() const
void Insert(sal_uInt16 nPos, const Point &rPt)
sal_uInt16 GetSize() const
void SetFlags(sal_uInt16 nPos, PolyFlags eFlags)
constexpr Point Center() const
constexpr tools::Long GetWidth() const
constexpr tools::Long Top() const
constexpr Point TopLeft() const
void SetPos(const Point &rPoint)
constexpr Size GetSize() const
constexpr tools::Long Right() const
constexpr tools::Long GetHeight() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
void SaturatingSetSize(const Size &rSize)
static bool IsFuzzing()
tools::Long GetFontHeight() const
void SetFontSize(const Size &)
void SetOrientation(Degree10 nLineOrientation)
void SetAverageFontWidth(tools::Long nWidth)
void SetPitch(FontPitch ePitch)
void SetTransparent(bool bTransparent)
void SetFillColor(const Color &)
void SetColor(const Color &)
const OUString & GetStyleName() const
void SetItalic(FontItalic)
void SetWeight(FontWeight)
void SetFontHeight(tools::Long nHeight)
bool IsTransparent() const
tools::Long GetOrCalculateAverageFontWidth() const
const OUString & GetFamilyName() const
void SetFamily(FontFamily)
void SetUnderline(FontLineStyle)
TextAlign GetAlignment() const
void SetCharSet(rtl_TextEncoding)
const Size & GetFontSize() const
const Color & GetColor() const
void SetAlignment(TextAlign)
void SetFamilyName(const OUString &rFamilyName)
Degree10 GetOrientation() const
const Color & GetFillColor() const
tools::Long GetAverageFontWidth() const
void SetStrikeout(FontStrikeout)
constexpr ::Color COL_GRAY(0x80, 0x80, 0x80)
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
constexpr ::Color COL_GRAY7(0x66, 0x66, 0x66)
ColorTransparency
constexpr ::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
int nCount
UNOTOOLS_DLLPUBLIC OUString utl_getLocaleForGlobalDefaultEncoding()
EmbeddedObjectRef * pObject
std::deque< AttacherIndex_Impl > aIndex
LINESTYLE_SINGLE
STRIKEOUT_SINGLE
FontPitch
PITCH_VARIABLE
PITCH_FIXED
ITALIC_NORMAL
ALIGN_BOTTOM
ALIGN_TOP
ALIGN_BASELINE
FontFamily
FAMILY_DECORATIVE
FAMILY_DONTKNOW
FAMILY_SCRIPT
FAMILY_SWISS
FAMILY_MODERN
FAMILY_ROMAN
WEIGHT_ULTRALIGHT
WEIGHT_ULTRABOLD
WEIGHT_THIN
WEIGHT_BOLD
WEIGHT_NORMAL
WEIGHT_LIGHT
WEIGHT_DONTKNOW
WEIGHT_SEMIBOLD
WEIGHT_MEDIUM
WEIGHT_BLACK
SvStream & WriteSvtGraphicFill(SvStream &rOStm, const SvtGraphicFill &rClass)
sal_Int32 nIndex
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
#define EMFP_DEBUG(x)
Definition: mtftools.cxx:43
def text(shape, orig_st)
NONE
bool isRectangle(const B2DPolygon &rPoly)
constexpr double rad2deg(double v)
B2IRange fround(const B2DRange &rRange)
static SvStream & operator>>(SvStream &rStream, sal_Int16 &n)
Definition: emfreader.cxx:629
TextAlignmentMode
Definition: mtftools.hxx:172
@ TA_TOP
Definition: mtftools.hxx:179
@ TA_BASELINE
Definition: mtftools.hxx:183
@ TA_BOTTOM
Definition: mtftools.hxx:180
@ TA_RIGHT_CENTER
Definition: mtftools.hxx:178
@ TA_NOUPDATECP
Definition: mtftools.hxx:173
@ TA_CENTER
Definition: mtftools.hxx:177
@ TA_UPDATECP
Definition: mtftools.hxx:174
@ TA_LEFT
Definition: mtftools.hxx:175
@ SRCPAINT
Definition: mtftools.hxx:193
@ SRCAND
Definition: mtftools.hxx:194
@ PATINVERT
Definition: mtftools.hxx:198
@ SRCINVERT
Definition: mtftools.hxx:195
GraphicsMode
Definition: mtftools.hxx:116
constexpr sal_uInt32 ENHMETA_STOCK_OBJECT
Definition: mtftools.hxx:63
@ FW_MEDIUM
Definition: mtftools.hxx:297
@ FW_ULTRALIGHT
Definition: mtftools.hxx:301
@ FW_LIGHT
Definition: mtftools.hxx:295
@ FW_ULTRABOLD
Definition: mtftools.hxx:302
@ FW_SEMIBOLD
Definition: mtftools.hxx:298
@ FW_THIN
Definition: mtftools.hxx:293
@ FW_BOLD
Definition: mtftools.hxx:299
@ PS_COSMETIC
Definition: mtftools.hxx:206
RegionMode
Definition: mtftools.hxx:37
ModifyWorldTransformMode
Definition: mtftools.hxx:56
WMFRasterOp
Definition: mtftools.hxx:86
constexpr sal_Int32 MS_FIXPOINT_BITCOUNT_28_4
Definition: mtftools.hxx:328
BackgroundMode
Definition: mtftools.hxx:47
MappingMode
Definition: mtftools.hxx:99
@ MM_HIMETRIC
Definition: mtftools.hxx:102
@ MM_LOENGLISH
Definition: mtftools.hxx:103
@ MM_TEXT
Definition: mtftools.hxx:100
@ MM_HIENGLISH
Definition: mtftools.hxx:104
@ MM_ISOTROPIC
Definition: mtftools.hxx:106
@ MM_TWIPS
Definition: mtftools.hxx:105
@ MM_LOMETRIC
Definition: mtftools.hxx:101
StockObject
Definition: mtftools.hxx:68
constexpr sal_Int32 UNDOCUMENTED_WIN_RCL_RELATION
Definition: mtftools.hxx:327
@ DEFAULT_CHARSET
Definition: mtftools.hxx:236
@ OEM_CHARSET
Definition: mtftools.hxx:242
@ FF_SCRIPT
Definition: mtftools.hxx:287
@ FF_DECORATIVE
Definition: mtftools.hxx:288
@ FF_ROMAN
Definition: mtftools.hxx:284
@ FF_SWISS
Definition: mtftools.hxx:285
@ FF_MODERN
Definition: mtftools.hxx:286
@ VARIABLE_PITCH
Definition: mtftools.hxx:277
@ FIXED_PITCH
Definition: mtftools.hxx:276
@ DEFAULT_PITCH
Definition: mtftools.hxx:275
int i
index
std::enable_if< std::is_signed< T >::value, bool >::type checked_add(T a, T b, T &result)
std::enable_if< std::is_signed< T >::value, T >::type saturating_toggle_sign(T a)
std::enable_if< std::is_signed< T >::value, bool >::type checked_multiply(T a, T b, T &result)
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
std::enable_if< std::is_signed< T >::value, bool >::type checked_sub(T a, T b, T &result)
TextAlign
FontWeight
long Long
void DrawAndClipBitmap(const Point &rPos, const Size &rSize, const BitmapEx &rBitmap, BitmapEx &aBmpEx, basegfx::B2DPolyPolygon const &rClipPath)
ComplexTextLayoutFlags
::tools::Rectangle rectangleFromB2DRectangle(const basegfx::B2DRange &rRect)
sal_uInt32 nWinRop
Definition: mtftools.hxx:597
tools::Rectangle aOutRect
Definition: mtftools.hxx:596
sal_uInt8 lfUnderline
Definition: mtftools.hxx:144
sal_Int32 lfEscapement
Definition: mtftools.hxx:140
sal_uInt8 lfPitchAndFamily
Definition: mtftools.hxx:150
sal_Int32 lfWeight
Definition: mtftools.hxx:142
sal_uInt8 lfStrikeOut
Definition: mtftools.hxx:145
sal_Int32 lfWidth
Definition: mtftools.hxx:139
sal_uInt8 lfItalic
Definition: mtftools.hxx:143
sal_Int32 lfHeight
Definition: mtftools.hxx:138
sal_uInt8 lfCharSet
Definition: mtftools.hxx:146
OUString alfFaceName
Definition: mtftools.hxx:151
WinMtfFillStyleType aType
Definition: mtftools.hxx:406
WinMtfFontStyle(LOGFONTW const &rLogFont)
Definition: mtftools.cxx:166
std::vector< Color > aPaletteColors
Definition: mtftools.hxx:438
sal_Int32 one
#define OPAQUE
unsigned char sal_uInt8
UNOTOOLS_DLLPUBLIC rtl_TextEncoding utl_getWinTextEncodingFromLangStr(const OUString &sLanguage, bool bOEM=false)
sal_Int32 nLength