/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
constchar* emfTypeToName(sal_uInt16 type)
{ switch (type)
{ case EmfPlusRecordTypeHeader: return"EmfPlusRecordTypeHeader"; case EmfPlusRecordTypeEndOfFile: return"EmfPlusRecordTypeEndOfFile"; case EmfPlusRecordTypeComment: return"EmfPlusRecordTypeComment"; case EmfPlusRecordTypeGetDC: return"EmfPlusRecordTypeGetDC"; case EmfPlusRecordTypeObject: return"EmfPlusRecordTypeObject"; case EmfPlusRecordTypeFillRects: return"EmfPlusRecordTypeFillRects"; case EmfPlusRecordTypeDrawRects: return"EmfPlusRecordTypeDrawRects"; case EmfPlusRecordTypeFillPolygon: return"EmfPlusRecordTypeFillPolygon"; case EmfPlusRecordTypeDrawLines: return"EmfPlusRecordTypeDrawLines"; case EmfPlusRecordTypeFillClosedCurve: return"EmfPlusRecordTypeFillClosedCurve"; case EmfPlusRecordTypeDrawClosedCurve: return"EmfPlusRecordTypeDrawClosedCurve"; case EmfPlusRecordTypeDrawCurve: return"EmfPlusRecordTypeDrawCurve"; case EmfPlusRecordTypeFillEllipse: return"EmfPlusRecordTypeFillEllipse"; case EmfPlusRecordTypeDrawEllipse: return"EmfPlusRecordTypeDrawEllipse"; case EmfPlusRecordTypeFillPie: return"EmfPlusRecordTypeFillPie"; case EmfPlusRecordTypeDrawPie: return"EmfPlusRecordTypeDrawPie"; case EmfPlusRecordTypeDrawArc: return"EmfPlusRecordTypeDrawArc"; case EmfPlusRecordTypeFillRegion: return"EmfPlusRecordTypeFillRegion"; case EmfPlusRecordTypeFillPath: return"EmfPlusRecordTypeFillPath"; case EmfPlusRecordTypeDrawPath: return"EmfPlusRecordTypeDrawPath"; case EmfPlusRecordTypeDrawBeziers: return"EmfPlusRecordTypeDrawBeziers"; case EmfPlusRecordTypeDrawImage: return"EmfPlusRecordTypeDrawImage"; case EmfPlusRecordTypeDrawImagePoints: return"EmfPlusRecordTypeDrawImagePoints"; case EmfPlusRecordTypeDrawString: return"EmfPlusRecordTypeDrawString"; case EmfPlusRecordTypeSetRenderingOrigin: return"EmfPlusRecordTypeSetRenderingOrigin"; case EmfPlusRecordTypeSetAntiAliasMode: return"EmfPlusRecordTypeSetAntiAliasMode"; case EmfPlusRecordTypeSetTextRenderingHint: return"EmfPlusRecordTypeSetTextRenderingHint"; case EmfPlusRecordTypeSetTextContrast: return"EmfPlusRecordTypeSetTextContrast"; case EmfPlusRecordTypeSetInterpolationMode: return"EmfPlusRecordTypeSetInterpolationMode"; case EmfPlusRecordTypeSetPixelOffsetMode: return"EmfPlusRecordTypeSetPixelOffsetMode"; case EmfPlusRecordTypeSetCompositingQuality: return"EmfPlusRecordTypeSetCompositingQuality"; case EmfPlusRecordTypeSave: return"EmfPlusRecordTypeSave"; case EmfPlusRecordTypeRestore: return"EmfPlusRecordTypeRestore"; case EmfPlusRecordTypeBeginContainer: return"EmfPlusRecordTypeBeginContainer"; case EmfPlusRecordTypeBeginContainerNoParams: return"EmfPlusRecordTypeBeginContainerNoParams"; case EmfPlusRecordTypeEndContainer: return"EmfPlusRecordTypeEndContainer"; case EmfPlusRecordTypeSetWorldTransform: return"EmfPlusRecordTypeSetWorldTransform"; case EmfPlusRecordTypeResetWorldTransform: return"EmfPlusRecordTypeResetWorldTransform"; case EmfPlusRecordTypeMultiplyWorldTransform: return"EmfPlusRecordTypeMultiplyWorldTransform"; case EmfPlusRecordTypeTranslateWorldTransform: return"EmfPlusRecordTypeTranslateWorldTransform"; case EmfPlusRecordTypeScaleWorldTransform: return"EmfPlusRecordTypeScaleWorldTransform"; case EmfPlusRecordTypeSetPageTransform: return"EmfPlusRecordTypeSetPageTransform"; case EmfPlusRecordTypeResetClip: return"EmfPlusRecordTypeResetClip"; case EmfPlusRecordTypeSetClipRect: return"EmfPlusRecordTypeSetClipRect"; case EmfPlusRecordTypeSetClipPath: return"EmfPlusRecordTypeSetClipPath"; case EmfPlusRecordTypeSetClipRegion: return"EmfPlusRecordTypeSetClipRegion"; case EmfPlusRecordTypeOffsetClip: return"EmfPlusRecordTypeOffsetClip"; case EmfPlusRecordTypeDrawDriverString: return"EmfPlusRecordTypeDrawDriverString";
} return"";
}
static OUString emfObjectToName(sal_uInt16 type)
{ switch (type)
{ case EmfPlusObjectTypeBrush: return u"EmfPlusObjectTypeBrush"_ustr; case EmfPlusObjectTypePen: return u"EmfPlusObjectTypePen"_ustr; case EmfPlusObjectTypePath: return u"EmfPlusObjectTypePath"_ustr; case EmfPlusObjectTypeRegion: return u"EmfPlusObjectTypeRegion"_ustr; case EmfPlusObjectTypeImage: return u"EmfPlusObjectTypeImage"_ustr; case EmfPlusObjectTypeFont: return u"EmfPlusObjectTypeFont"_ustr; case EmfPlusObjectTypeStringFormat: return u"EmfPlusObjectTypeStringFormat"_ustr; case EmfPlusObjectTypeImageAttributes: return u"EmfPlusObjectTypeImageAttributes"_ustr; case EmfPlusObjectTypeCustomLineCap: return u"EmfPlusObjectTypeCustomLineCap"_ustr;
} return u""_ustr;
}
static OUString PixelOffsetModeToString(sal_uInt16 nPixelOffset)
{ switch (nPixelOffset)
{ case PixelOffsetMode::PixelOffsetModeDefault: return u"PixelOffsetModeDefault"_ustr; case PixelOffsetMode::PixelOffsetModeHighSpeed: return u"PixelOffsetModeHighSpeed"_ustr; case PixelOffsetMode::PixelOffsetModeHighQuality: return u"PixelOffsetModeHighQuality"_ustr; case PixelOffsetMode::PixelOffsetModeNone: return u"PixelOffsetModeNone"_ustr; case PixelOffsetMode::PixelOffsetModeHalf: return u"PixelOffsetModeHalf"_ustr;
} return u""_ustr;
}
static OUString SmoothingModeToString(sal_uInt16 nSmoothMode)
{ switch (nSmoothMode)
{ case SmoothingMode::SmoothingModeDefault: return u"SmoothingModeDefault"_ustr; case SmoothingMode::SmoothingModeHighSpeed: return u"SmoothModeHighSpeed"_ustr; case SmoothingMode::SmoothingModeHighQuality: return u"SmoothingModeHighQuality"_ustr; case SmoothingMode::SmoothingModeNone: return u"SmoothingModeNone"_ustr; case SmoothingMode::SmoothingModeAntiAlias8x4: return u"SmoothingModeAntiAlias8x4"_ustr; case SmoothingMode::SmoothingModeAntiAlias8x8: return u"SmoothingModeAntiAlias8x8"_ustr;
} return u""_ustr;
}
static OUString TextRenderingHintToString(sal_uInt16 nHint)
{ switch (nHint)
{ case TextRenderingHint::TextRenderingHintSystemDefault: return u"TextRenderingHintSystemDefault"_ustr; case TextRenderingHint::TextRenderingHintSingleBitPerPixelGridFit: return u"TextRenderingHintSingleBitPerPixelGridFit"_ustr; case TextRenderingHint::TextRenderingHintSingleBitPerPixel: return u"TextRenderingHintSingleBitPerPixel"_ustr; case TextRenderingHint::TextRenderingHintAntialiasGridFit: return u"TextRenderingHintAntialiasGridFit"_ustr; case TextRenderingHint::TextRenderingHintAntialias: return u"TextRenderingHintAntialias"_ustr; case TextRenderingHint::TextRenderingHintClearTypeGridFit: return u"TextRenderingHintClearTypeGridFit"_ustr;
} return u""_ustr;
}
static OUString InterpolationModeToString(sal_uInt16 nMode)
{ switch (nMode)
{ case InterpolationMode::InterpolationModeDefault: return u"InterpolationModeDefault"_ustr; case InterpolationMode::InterpolationModeLowQuality: return u"InterpolationModeLowQuality"_ustr; case InterpolationMode::InterpolationModeHighQuality: return u"InterpolationModeHighQuality"_ustr; case InterpolationMode::InterpolationModeBilinear: return u"InterpolationModeBilinear"_ustr; case InterpolationMode::InterpolationModeBicubic: return u"InterpolationModeBicubic"_ustr; case InterpolationMode::InterpolationModeNearestNeighbor: return u"InterpolationModeNearestNeighbor"_ustr; case InterpolationMode::InterpolationModeHighQualityBilinear: return u"InterpolationModeHighQualityBilinear"_ustr; case InterpolationMode::InterpolationModeHighQualityBicubic: return u"InterpolationModeHighQualityBicubic"_ustr;
} return u""_ustr;
}
OUString UnitTypeToString(sal_uInt16 nType)
{ switch (nType)
{ case UnitTypeWorld: return u"UnitTypeWorld"_ustr; case UnitTypeDisplay: return u"UnitTypeDisplay"_ustr; case UnitTypePixel: return u"UnitTypePixel"_ustr; case UnitTypePoint: return u"UnitTypePoint"_ustr; case UnitTypeInch: return u"UnitTypeInch"_ustr; case UnitTypeDocument: return u"UnitTypeDocument"_ustr; case UnitTypeMillimeter: return u"UnitTypeMillimeter"_ustr;
} return u""_ustr;
}
double EmfPlusHelperData::unitToPixel(double n, sal_uInt32 aUnitType, Direction d)
{ switch (static_cast<UnitType>(aUnitType))
{ case UnitTypePixel: return n;
case UnitTypePoint: return o3tl::convert(n, o3tl::Length::pt, o3tl::Length::in) * DPI(d);
case UnitTypeInch: return n * DPI(d);
case UnitTypeMillimeter: return o3tl::convert(n, o3tl::Length::mm, o3tl::Length::in) * DPI(d);
case UnitTypeDocument: return n * DPI(d) / 300.0;
case UnitTypeWorld: case UnitTypeDisplay:
SAL_WARN("drawinglayer.emf", "EMF+\t Converting to World/Display."); return n;
default:
SAL_WARN("drawinglayer.emf", "EMF+\tTODO Unimplemented support of Unit Type: 0x" << std::hex << aUnitType); return n;
}
}
switch (objecttype)
{ case EmfPlusObjectTypeBrush:
{
EMFPBrush *brush = new EMFPBrush();
maEMFPObjects[index].reset(brush);
brush->Read(rObjectStream, *this); break;
} case EmfPlusObjectTypePen:
{
EMFPPen *pen = new EMFPPen();
maEMFPObjects[index].reset(pen);
pen->Read(rObjectStream, *this);
pen->penWidth = unitToPixel(pen->penWidth, pen->penUnit, Direction::horizontal); break;
} case EmfPlusObjectTypePath:
{
sal_uInt32 aVersion, aPathPointCount, aPathPointFlags;
rObjectStream.ReadUInt32(aVersion).ReadUInt32(aPathPointCount).ReadUInt32(aPathPointFlags);
SAL_INFO("drawinglayer.emf", "EMF+\t\tVersion: 0x" << std::hex << aVersion);
SAL_INFO("drawinglayer.emf", "EMF+\t\tNumber of points: " << std::dec << aPathPointCount);
SAL_INFO("drawinglayer.emf", "EMF+\t\tPath point flags: 0x" << std::hex << aPathPointFlags << std::dec);
EMFPPath *path = new EMFPPath(aPathPointCount);
maEMFPObjects[index].reset(path);
path->Read(rObjectStream, aPathPointFlags); break;
} case EmfPlusObjectTypeRegion:
{
EMFPRegion *region = new EMFPRegion();
maEMFPObjects[index].reset(region);
region->ReadRegion(rObjectStream, *this); break;
} case EmfPlusObjectTypeImage:
{
EMFPImage *image = new EMFPImage;
maEMFPObjects[index].reset(image);
image->type = 0;
image->width = 0;
image->height = 0;
image->stride = 0;
image->pixelFormat = 0;
image->Read(rObjectStream, dataSize, bUseWholeStream); break;
} case EmfPlusObjectTypeFont:
{
EMFPFont *font = new EMFPFont;
maEMFPObjects[index].reset(font);
font->emSize = 0;
font->sizeUnit = 0;
font->fontFlags = 0;
font->Read(rObjectStream); // tdf#113624 Convert unit to Pixels
font->emSize = unitToPixel(font->emSize, font->sizeUnit, Direction::horizontal);
break;
} case EmfPlusObjectTypeStringFormat:
{
EMFPStringFormat *stringFormat = new EMFPStringFormat();
maEMFPObjects[index].reset(stringFormat);
stringFormat->Read(rObjectStream); break;
} case EmfPlusObjectTypeImageAttributes:
{
EMFPImageAttributes *imageAttributes = new EMFPImageAttributes();
maEMFPObjects[index].reset(imageAttributes);
imageAttributes->Read(rObjectStream); break;
} case EmfPlusObjectTypeCustomLineCap:
{
SAL_WARN("drawinglayer.emf", "EMF+\t TODO Object type 'custom line cap' not yet implemented"); break;
} default:
{
SAL_WARN("drawinglayer.emf", "EMF+\t TODO Object unhandled flags: 0x" << std::hex << (flags & 0xff00) << std::dec);
}
}
}
void EmfPlusHelperData::ReadPoint(SvStream& s, float& x, float& y, sal_uInt32 flags)
{ if (flags & 0x800)
{ // specifies a location in the coordinate space that is relative to // the location specified by the previous element in the array. In the case of the first element in // PointData, a previous location at coordinates (0,0) is assumed.
SAL_WARN("drawinglayer.emf", "EMF+\t\t TODO Relative coordinates bit detected. Implement parse EMFPlusPointR");
}
if (flags & 0x4000)
{
sal_Int16 ix, iy;
s.ReadInt16(ix).ReadInt16(iy);
x = ix;
y = iy;
} else
{
s.ReadFloat(x).ReadFloat(y);
}
}
void EmfPlusHelperData::mappingChanged()
{ if (mnPixX == 0 || mnPixY == 0)
{
SAL_WARN("drawinglayer.emf", "dimensions in pixels is 0"); return;
} // Call when mnMmX/mnMmY/mnPixX/mnPixY/mnFrameLeft/mnFrameTop/maWorldTransform/ changes. // Currently not used are mnHDPI/mnVDPI/mnFrameRight/mnFrameBottom. *If* these should // be used in the future, this method will need to be called. // // Re-calculate maMapTransform to contain the complete former transformation so that // it can be applied by a single matrix multiplication or be added to an encapsulated // primitive later // // To evtl. correct and see where this came from, please compare with the implementations // of EmfPlusHelperData::MapToDevice and EmfPlusHelperData::Map* in prev versions
maMapTransform = maWorldTransform;
maMapTransform *= basegfx::utils::createScaleTranslateB2DHomMatrix(100.0 * mnMmX / mnPixX, 100.0 * mnMmY / mnPixY, double(-mnFrameLeft), double(-mnFrameTop));
maMapTransform *= maBaseTransform;
// Used only for performance optimization, to do not calculate it every line draw
mdExtractedXScale = std::hypot(maMapTransform.a(), maMapTransform.b());
mdExtractedYScale = std::hypot(maMapTransform.c(), maMapTransform.d());
}
::basegfx::B2DPoint EmfPlusHelperData::Map(double ix, double iy) const
{ // map in one step using complete MapTransform (see mappingChanged) return maMapTransform * ::basegfx::B2DPoint(ix, iy);
}
Color EmfPlusHelperData::EMFPGetBrushColorOrARGBColor(const sal_uInt16 flags, const sal_uInt32 brushIndexOrColor) const {
Color color; if (flags & 0x8000) // we use a color
{
color = Color(ColorAlpha, (brushIndexOrColor >> 24), (brushIndexOrColor >> 16) & 0xff,
(brushIndexOrColor >> 8) & 0xff, brushIndexOrColor & 0xff);
} else// we use a brush
{ const EMFPBrush* brush = dynamic_cast<EMFPBrush*>(maEMFPObjects[brushIndexOrColor & 0xff].get()); if (brush)
{
color = brush->GetColor(); if (brush->type != BrushTypeSolidColor)
SAL_WARN("drawinglayer.emf", "EMF+\t\t TODO Brush other than solid color is not supported");
}
} return color;
}
void EmfPlusHelperData::GraphicStatePush(GraphicStateMap& map, sal_Int32 index)
{
GraphicStateMap::iterator iter = map.find( index );
if ( iter != map.end() )
{
map.erase( iter );
SAL_INFO("drawinglayer.emf", "EMF+\t\tStack index: " << index << " found and erased");
}
wmfemfhelper::PropertyHolder state = mrPropertyHolders.Current(); // tdf#112500 We need to save world transform somehow, during graphic state push
state.setTransformation(maWorldTransform);
map[ index ] = std::move(state);
}
void EmfPlusHelperData::GraphicStatePop(GraphicStateMap& map, sal_Int32 index)
{
GraphicStateMap::iterator iter = map.find(index);
if (iter != map.end())
{
wmfemfhelper::PropertyHolder state = iter->second;
maWorldTransform = state.getTransformation(); if (state.getClipPolyPolygonActive())
{
SAL_INFO("drawinglayer.emf", "EMF+\t Restore clipping region to saved in index: " << index);
wmfemfhelper::HandleNewClipRegion(state.getClipPolyPolygon(), mrTargetHolders,
mrPropertyHolders);
} else
{
SAL_INFO("drawinglayer.emf", "EMF+\t Disable clipping");
wmfemfhelper::HandleNewClipRegion(::basegfx::B2DPolyPolygon(), mrTargetHolders,
mrPropertyHolders);
}
mappingChanged();
SAL_INFO("drawinglayer.emf", "EMF+\t\tStack index: " << index
<< " found, maWorldTransform: " << maWorldTransform);
}
}
if (isColor) // use Color
{
SAL_INFO("drawinglayer.emf", "EMF+\t\t Fill polygon, ARGB color: 0x" << std::hex << brushIndexOrColor << std::dec);
// EMF Alpha (1 byte): An 8-bit unsigned integer that specifies the transparency of the background, // ranging from 0 for completely transparent to 0xFF for completely opaque. const Color color(ColorAlpha, (brushIndexOrColor >> 24), (brushIndexOrColor >> 16) & 0xff, (brushIndexOrColor >> 8) & 0xff, brushIndexOrColor & 0xff);
EMFPPlusFillPolygonSolidColor(polygon, color);
if (brush->type == BrushTypeSolidColor)
{
Color fillColor = brush->solidColor;
EMFPPlusFillPolygonSolidColor(polygon, fillColor);
} elseif (brush->type == BrushTypeHatchFill)
{ // EMF+ like hatching is currently not supported. These are just color blends which serve as an approximation for some of them // for the others the hatch "background" color (secondColor in brush) is used.
if (brush->blendPositions)
{
SAL_INFO("drawinglayer.emf", "EMF+\t\tUse blend");
// store the blendpoints in the vector for (sal_uInt32 i = 0; i < brush->blendPoints; i++)
{ constdouble aBlendPoint = brush->blendPositions[i];
basegfx::BColor aColor;
aColor.setGreen(aStartColor.getGreen() + brush->blendFactors[i] * (aEndColor.getGreen() - aStartColor.getGreen()));
aColor.setBlue (aStartColor.getBlue() + brush->blendFactors[i] * (aEndColor.getBlue() - aStartColor.getBlue()));
aColor.setRed (aStartColor.getRed() + brush->blendFactors[i] * (aEndColor.getRed() - aStartColor.getRed())); constdouble aAlpha = brush->solidColor.GetAlpha() + brush->blendFactors[i] * (brush->secondColor.GetAlpha() - brush->solidColor.GetAlpha());
aVector.emplace_back(aBlendPoint, aColor, aAlpha / 255.0);
}
} elseif (brush->colorblendPositions)
{
SAL_INFO("drawinglayer.emf", "EMF+\t\tUse color blend");
// store the colorBlends in the vector for (sal_uInt32 i = 0; i < brush->colorblendPoints; i++)
{ constdouble aBlendPoint = brush->colorblendPositions[i]; const basegfx::BColor aColor = brush->colorblendColors[i].getBColor();
aVector.emplace_back(aBlendPoint, aColor, brush->colorblendColors[i].GetAlpha() / 255.0);
}
} else// ok, no extra points: just start and end
{
aVector.emplace_back(0.0, aStartColor, brush->solidColor.GetAlpha() / 255.0);
aVector.emplace_back(1.0, aEndColor, brush->secondColor.GetAlpha() / 255.0);
}
// get the polygon range to be able to map the start/end/center point correctly // therefore, create a mapping and invert it
basegfx::B2DRange aPolygonRange= polygon.getB2DRange();
basegfx::B2DHomMatrix aPolygonTransformation = basegfx::utils::createScaleTranslateB2DHomMatrix(
aPolygonRange.getWidth(),aPolygonRange.getHeight(),
aPolygonRange.getMinX(), aPolygonRange.getMinY());
aPolygonTransformation.invert();
if (brush->type == BrushTypeLinearGradient)
{ // support for public enum EmfPlusWrapMode
basegfx::B2DPoint aStartPoint = Map(brush->firstPointX, 0.0);
aStartPoint = aPolygonTransformation * aStartPoint;
basegfx::B2DPoint aEndPoint = Map(brush->firstPointX + brush->aWidth, 0.0);
aEndPoint = aPolygonTransformation * aEndPoint;
// support for public enum EmfPlusWrapMode
drawinglayer::primitive2d::SpreadMethod aSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Pad); switch(brush->wrapMode)
{ case WrapModeTile: case WrapModeTileFlipY:
{
aSpreadMethod = drawinglayer::primitive2d::SpreadMethod::Repeat; break;
} case WrapModeTileFlipX: case WrapModeTileFlipXY:
{
aSpreadMethod = drawinglayer::primitive2d::SpreadMethod::Reflect; break;
} default: break;
}
// create the same one used for SVG
mrTargetHolders.Current().append( new drawinglayer::primitive2d::SvgLinearGradientPrimitive2D(
aTextureTransformation,
polygon,
std::move(aVector),
aStartPoint,
aEndPoint, false, // do not use UnitCoordinates
aSpreadMethod));
} else// BrushTypePathGradient
{ // TODO The PathGradient is not implemented, and Radial Gradient is used instead
basegfx::B2DPoint aCenterPoint = Map(brush->firstPointX, brush->firstPointY);
aCenterPoint = aPolygonTransformation * aCenterPoint;
// create the same one used for SVG
mrTargetHolders.Current().append( new drawinglayer::primitive2d::SvgRadialGradientPrimitive2D(
aTextureTransformation,
polygon,
std::move(aVector),
aCenterPoint,
0.7, // relative radius little bigger to cover all elements true, // use UnitCoordinates to stretch the gradient
drawinglayer::primitive2d::SpreadMethod::Pad,
nullptr));
}
}
}
}
::basegfx::B2DPolyPolygon EmfPlusHelperData::combineClip(::basegfx::B2DPolyPolygon const & leftPolygon, int combineMode, ::basegfx::B2DPolyPolygon const & rightPolygon)
{
basegfx::B2DPolyPolygon aClippedPolyPolygon; switch (combineMode)
{ case EmfPlusCombineModeReplace:
{
aClippedPolyPolygon = rightPolygon; break;
} case EmfPlusCombineModeIntersect:
{
aClippedPolyPolygon = basegfx::utils::clipPolyPolygonOnPolyPolygon(
leftPolygon, rightPolygon, true, false); break;
} case EmfPlusCombineModeUnion:
{
aClippedPolyPolygon = ::basegfx::utils::solvePolygonOperationOr(leftPolygon, rightPolygon); break;
} case EmfPlusCombineModeXOR:
{
aClippedPolyPolygon = ::basegfx::utils::solvePolygonOperationXor(leftPolygon, rightPolygon); break;
} case EmfPlusCombineModeExclude:
{ // Replaces the existing region with the part of itself that is not in the new region.
aClippedPolyPolygon = ::basegfx::utils::solvePolygonOperationDiff(leftPolygon, rightPolygon); break;
} case EmfPlusCombineModeComplement:
{ // Replaces the existing region with the part of the new region that is not in the existing region.
aClippedPolyPolygon = ::basegfx::utils::solvePolygonOperationDiff(rightPolygon, leftPolygon); break;
}
} return aClippedPolyPolygon;
}
if (size < 12)
{
SAL_WARN("drawinglayer.emf", "Size field is less than 12 bytes"); break;
} elseif (size > length)
{
SAL_WARN("drawinglayer.emf", "Size field is greater than bytes left"); break;
}
if (dataSize > (size - 12))
{
SAL_WARN("drawinglayer.emf", "DataSize field is greater than Size-12"); break;
}
EMFPRegion* region = dynamic_cast<EMFPRegion*>(maEMFPObjects[flags & 0xff].get()); if (region)
EMFPPlusFillPolygon(region->regionPolyPolygon, flags & 0x8000, brushIndexOrColor); else
SAL_WARN("drawinglayer.emf", "EMF+\tEmfPlusRecordTypeFillRegion missing region");
} break; case EmfPlusRecordTypeDrawEllipse: case EmfPlusRecordTypeFillEllipse:
{ // Intentionally very bogus initial value to avoid MSVC complaining about potentially uninitialized local // variable. As long as the code stays as intended, this variable will be assigned a (real) value in the case // when it is later used.
sal_uInt32 brushIndexOrColor = 1234567;
if (type == EmfPlusRecordTypeFillEllipse)
{
rMS.ReadUInt32(brushIndexOrColor);
}
// 0x2000 bit indicates whether to draw an extra line between the last point // and the first point, to close the shape.
EMFPPlusDrawPolygon(path.GetPolygon(*this, true, (flags & 0x2000)), flags);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.