diff options
author | Bartosz Kosiorek <gang65@poczta.onet.pl> | 2021-06-23 16:55:21 +0200 |
---|---|---|
committer | Bartosz Kosiorek <gang65@poczta.onet.pl> | 2021-06-23 18:24:38 +0200 |
commit | 9e8c35cc3f1f5e1c08afd46e0d0fbc07f1ff21f9 (patch) | |
tree | 90253277cb17adcc51485a83d5b08e137f056785 /drawinglayer | |
parent | 177167dcff92a48ca7fcf66d8cf20f38e560c5b3 (diff) |
EMF+ tdf#142975 Add brush support to DrawString record
Change-Id: Icfcb4199dcd755fb20e14a8166571b6d6e763f2e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117671
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
Diffstat (limited to 'drawinglayer')
-rw-r--r-- | drawinglayer/source/tools/emfphelperdata.cxx | 267 | ||||
-rw-r--r-- | drawinglayer/source/tools/primitive2dxmldump.cxx | 82 |
2 files changed, 177 insertions, 172 deletions
diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx index b56e51000211..b052c1551d69 100644 --- a/drawinglayer/source/tools/emfphelperdata.cxx +++ b/drawinglayer/source/tools/emfphelperdata.cxx @@ -456,12 +456,14 @@ namespace emfplushelper color = Color(ColorAlpha, (brushIndexOrColor >> 24), (brushIndexOrColor >> 16) & 0xff, (brushIndexOrColor >> 8) & 0xff, brushIndexOrColor & 0xff); } - else // we use a pen + else // we use a brush { - const EMFPPen* pen = static_cast<EMFPPen*>(maEMFPObjects[brushIndexOrColor & 0xff].get()); - if (pen) + const EMFPBrush* brush = static_cast<EMFPBrush*>(maEMFPObjects[brushIndexOrColor & 0xff].get()); + if (brush) { - color = pen->GetColor(); + 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; @@ -1525,161 +1527,152 @@ namespace emfplushelper } case EmfPlusRecordTypeDrawString: { - sal_uInt32 brushId; - sal_uInt32 formatId; - sal_uInt32 stringLength; + sal_uInt32 brushId, formatId, stringLength; rMS.ReadUInt32(brushId).ReadUInt32(formatId).ReadUInt32(stringLength); SAL_INFO("drawinglayer.emf", "EMF+\t FontId: " << OUString::number(flags & 0xFF)); SAL_INFO("drawinglayer.emf", "EMF+\t BrushId: " << BrushIDToString(flags, brushId)); SAL_INFO("drawinglayer.emf", "EMF+\t FormatId: " << formatId); SAL_INFO("drawinglayer.emf", "EMF+\t Length: " << stringLength); - if (flags & 0x8000) + // read the layout rectangle + float lx, ly, lw, lh; + rMS.ReadFloat(lx).ReadFloat(ly).ReadFloat(lw).ReadFloat(lh); + + SAL_INFO("drawinglayer.emf", "EMF+\t DrawString layoutRect: " << lx << "," << ly << " - " << lw << "x" << lh); + // parse the string + const OUString text = read_uInt16s_ToOUString(rMS, stringLength); + SAL_INFO("drawinglayer.emf", "EMF+\t DrawString string: " << text); + // get the stringFormat from the Object table ( this is OPTIONAL and may be nullptr ) + const EMFPStringFormat *stringFormat = dynamic_cast<EMFPStringFormat*>(maEMFPObjects[formatId & 0xff].get()); + // get the font from the flags + const EMFPFont *font = static_cast< EMFPFont* >( maEMFPObjects[flags & 0xff].get() ); + if (!font) { - // read the layout rectangle - float lx, ly, lw, lh; - rMS.ReadFloat(lx).ReadFloat(ly).ReadFloat(lw).ReadFloat(lh); - - SAL_INFO("drawinglayer.emf", "EMF+\t DrawString layoutRect: " << lx << "," << ly << " - " << lw << "x" << lh); - // parse the string - const OUString text = read_uInt16s_ToOUString(rMS, stringLength); - SAL_INFO("drawinglayer.emf", "EMF+\t DrawString string: " << text); - // get the stringFormat from the Object table ( this is OPTIONAL and may be nullptr ) - const EMFPStringFormat *stringFormat = dynamic_cast<EMFPStringFormat*>(maEMFPObjects[formatId & 0xff].get()); - // get the font from the flags - const EMFPFont *font = static_cast< EMFPFont* >( maEMFPObjects[flags & 0xff].get() ); - if (!font) + break; + } + mrPropertyHolders.Current().setFont(vcl::Font(font->family, Size(font->emSize, font->emSize))); + + drawinglayer::attribute::FontAttribute fontAttribute( + font->family, // font family + "", // (no) font style + font->Bold() ? 8u : 1u, // weight: 8 = bold + font->family == "SYMBOL", // symbol + stringFormat && stringFormat->DirectionVertical(), // vertical + font->Italic(), // italic + false, // monospaced + false, // outline = false, no such thing in MS-EMFPLUS + stringFormat && stringFormat->DirectionRightToLeft(), // right-to-left + false); // BiDiStrong + + css::lang::Locale locale; + double stringAlignmentHorizontalOffset = 0.0; + if (stringFormat) + { + SAL_WARN_IF(stringFormat->DirectionRightToLeft(), "drawinglayer.emf", "EMF+\t DrawString Alignment TODO For a right-to-left layout rectangle, the origin should be at the upper right."); + if (stringFormat->stringAlignment == StringAlignmentNear) + // Alignment is to the left side of the layout rectangle (lx, ly, lw, lh) { - break; + stringAlignmentHorizontalOffset = stringFormat->leadingMargin * font->emSize; + } else if (stringFormat->stringAlignment == StringAlignmentCenter) + // Alignment is centered between the origin and extent of the layout rectangle + { + stringAlignmentHorizontalOffset = 0.5 * lw + stringFormat->leadingMargin * font->emSize - 0.3 * font->emSize * stringLength; + } else if (stringFormat->stringAlignment == StringAlignmentFar) + // Alignment is to the right side of the layout rectangle + { + stringAlignmentHorizontalOffset = lw - stringFormat->trailingMargin * font->emSize - 0.6 * font->emSize * stringLength; } - mrPropertyHolders.Current().setFont(vcl::Font(font->family, Size(font->emSize, font->emSize))); - drawinglayer::attribute::FontAttribute fontAttribute( - font->family, // font family - "", // (no) font style - font->Bold() ? 8u : 1u, // weight: 8 = bold - font->family == "SYMBOL", // symbol - stringFormat && stringFormat->DirectionVertical(), // vertical - font->Italic(), // italic - false, // monospaced - false, // outline = false, no such thing in MS-EMFPLUS - stringFormat && stringFormat->DirectionRightToLeft(), // right-to-left - false); // BiDiStrong - - css::lang::Locale locale; - double stringAlignmentHorizontalOffset = 0.0; - if (stringFormat) - { - SAL_WARN_IF(stringFormat->DirectionRightToLeft(), "drawinglayer.emf", "EMF+\t DrawString Alignment TODO For a right-to-left layout rectangle, the origin should be at the upper right."); - if (stringFormat->stringAlignment == StringAlignmentNear) - // Alignment is to the left side of the layout rectangle (lx, ly, lw, lh) - { - stringAlignmentHorizontalOffset = stringFormat->leadingMargin * font->emSize; - } else if (stringFormat->stringAlignment == StringAlignmentCenter) - // Alignment is centered between the origin and extent of the layout rectangle - { - stringAlignmentHorizontalOffset = 0.5 * lw + stringFormat->leadingMargin * font->emSize - 0.3 * font->emSize * stringLength; - } else if (stringFormat->stringAlignment == StringAlignmentFar) - // Alignment is to the right side of the layout rectangle - { - stringAlignmentHorizontalOffset = lw - stringFormat->trailingMargin * font->emSize - 0.6 * font->emSize * stringLength; - } + LanguageTag aLanguageTag(static_cast< LanguageType >(stringFormat->language)); + locale = aLanguageTag.getLocale(); + } + else + { + // By default LeadingMargin is 1/6 inch + // TODO for typographic fonts set value to 0. + stringAlignmentHorizontalOffset = 16.0; - LanguageTag aLanguageTag(static_cast< LanguageType >(stringFormat->language)); - locale = aLanguageTag.getLocale(); - } - else - { - // By default LeadingMargin is 1/6 inch - // TODO for typographic fonts set value to 0. - stringAlignmentHorizontalOffset = 16.0; + // use system default + locale = Application::GetSettings().GetLanguageTag().getLocale(); + } - // use system default - locale = Application::GetSettings().GetLanguageTag().getLocale(); - } + const basegfx::B2DHomMatrix transformMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix( + ::basegfx::B2DSize(font->emSize, font->emSize), + ::basegfx::B2DPoint(lx + stringAlignmentHorizontalOffset, ly + font->emSize)); - const basegfx::B2DHomMatrix transformMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix( - ::basegfx::B2DSize(font->emSize, font->emSize), - ::basegfx::B2DPoint(lx + stringAlignmentHorizontalOffset, ly + font->emSize)); + Color uncorrectedColor = EMFPGetBrushColorOrARGBColor(flags, brushId); + Color color; - Color uncorrectedColor = EMFPGetBrushColorOrARGBColor(flags, brushId); - Color color; + if (mbSetTextContrast) + { + const auto gammaVal = mnTextContrast / 1000; + const basegfx::BColorModifier_gamma gamma(gammaVal); + + // gamma correct transparency color + sal_uInt16 alpha = uncorrectedColor.GetAlpha(); + alpha = std::clamp(std::pow(alpha, 1.0 / gammaVal), 0.0, 1.0) * 255; + + basegfx::BColor modifiedColor(gamma.getModifiedColor(uncorrectedColor.getBColor())); + color.SetRed(modifiedColor.getRed() * 255); + color.SetGreen(modifiedColor.getGreen() * 255); + color.SetBlue(modifiedColor.getBlue() * 255); + color.SetAlpha(alpha); + } + else + { + color = uncorrectedColor; + } + + mrPropertyHolders.Current().setTextColor(color.getBColor()); + mrPropertyHolders.Current().setTextColorActive(true); - if (mbSetTextContrast) + if (color.GetAlpha() > 0) + { + std::vector<double> emptyVector; + rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pBaseText; + if (font->Underline() || font->Strikeout()) { - const auto gammaVal = mnTextContrast / 1000; - const basegfx::BColorModifier_gamma gamma(gammaVal); - - // gamma correct transparency color - sal_uInt16 alpha = uncorrectedColor.GetAlpha(); - alpha = std::clamp(std::pow(alpha, 1.0 / gammaVal), 0.0, 1.0) * 255; - - basegfx::BColor modifiedColor(gamma.getModifiedColor(uncorrectedColor.getBColor())); - color.SetRed(modifiedColor.getRed() * 255); - color.SetGreen(modifiedColor.getGreen() * 255); - color.SetBlue(modifiedColor.getBlue() * 255); - color.SetAlpha(alpha); + pBaseText = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D( + transformMatrix, + text, + 0, // text always starts at 0 + stringLength, + emptyVector, // EMF-PLUS has no DX-array + fontAttribute, + locale, + color.getBColor(), // Font Color + COL_TRANSPARENT, // Fill Color + color.getBColor(), // OverlineColor + color.getBColor(), // TextlineColor + drawinglayer::primitive2d::TEXT_LINE_NONE, + font->Underline() ? drawinglayer::primitive2d::TEXT_LINE_SINGLE : drawinglayer::primitive2d::TEXT_LINE_NONE, + false, + font->Strikeout() ? drawinglayer::primitive2d::TEXT_STRIKEOUT_SINGLE : drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE); } else { - color = uncorrectedColor; + pBaseText = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + transformMatrix, + text, + 0, // text always starts at 0 + stringLength, + emptyVector, // EMF-PLUS has no DX-array + fontAttribute, + locale, + color.getBColor()); } - - mrPropertyHolders.Current().setTextColor(color.getBColor()); - mrPropertyHolders.Current().setTextColorActive(true); - - if (color.GetAlpha() > 0) + drawinglayer::primitive2d::Primitive2DReference aPrimitiveText(pBaseText); + if (color.IsTransparent()) { - std::vector<double> emptyVector; - rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pBaseText; - if (font->Underline() || font->Strikeout()) - { - pBaseText = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D( - transformMatrix, - text, - 0, // text always starts at 0 - stringLength, - emptyVector, // EMF-PLUS has no DX-array - fontAttribute, - locale, - color.getBColor(), - COL_TRANSPARENT, - color.getBColor(), - color.getBColor(), - drawinglayer::primitive2d::TEXT_LINE_NONE, - font->Underline() ? drawinglayer::primitive2d::TEXT_LINE_SINGLE : drawinglayer::primitive2d::TEXT_LINE_NONE, - false, - font->Strikeout() ? drawinglayer::primitive2d::TEXT_STRIKEOUT_SINGLE : drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE); - } - else - { - pBaseText = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( - transformMatrix, - text, - 0, // text always starts at 0 - stringLength, - emptyVector, // EMF-PLUS has no DX-array - fontAttribute, - locale, - color.getBColor()); - } - drawinglayer::primitive2d::Primitive2DReference aPrimitiveText(pBaseText); - if (color.IsTransparent()) - { - aPrimitiveText = new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( - drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText }, - (255 - color.GetAlpha()) / 255.0); - } - - mrTargetHolders.Current().append( - new drawinglayer::primitive2d::TransformPrimitive2D( - maMapTransform, - drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText } )); + aPrimitiveText = new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( + drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText }, + (255 - color.GetAlpha()) / 255.0); } - } - else - { - SAL_WARN("drawinglayer.emf", "EMF+\t DrawString TODO - drawing with brush not yet supported"); + + mrTargetHolders.Current().append( + new drawinglayer::primitive2d::TransformPrimitive2D( + maMapTransform, + drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText } )); } break; } diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx index 9ed0e796fb01..4b0c47f41da0 100644 --- a/drawinglayer/source/tools/primitive2dxmldump.cxx +++ b/drawinglayer/source/tools/primitive2dxmldump.cxx @@ -25,6 +25,8 @@ #include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx> #include <drawinglayer/primitive2d/hiddengeometryprimitive2d.hxx> #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> +#include <primitive2d/textlineprimitive2d.hxx> #include <drawinglayer/primitive2d/textprimitive2d.hxx> #include <drawinglayer/primitive2d/maskprimitive2d.hxx> #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> @@ -56,6 +58,19 @@ OUString convertColorToString(const basegfx::BColor& rColor) return "#" + aRGBString; } +void writeMatrix(::tools::XmlWriter& rWriter, const basegfx::B2DHomMatrix& rMatrix) +{ + rWriter.attribute("xy11", rMatrix.get(0,0)); + rWriter.attribute("xy12", rMatrix.get(0,1)); + rWriter.attribute("xy13", rMatrix.get(0,2)); + rWriter.attribute("xy21", rMatrix.get(1,0)); + rWriter.attribute("xy22", rMatrix.get(1,1)); + rWriter.attribute("xy23", rMatrix.get(1,2)); + rWriter.attribute("xy31", rMatrix.get(2,0)); + rWriter.attribute("xy32", rMatrix.get(2,1)); + rWriter.attribute("xy33", rMatrix.get(2,2)); +} + void writePolyPolygon(::tools::XmlWriter& rWriter, const basegfx::B2DPolyPolygon& rB2DPolyPolygon) { rWriter.startElement("polypolygon"); @@ -211,17 +226,7 @@ void Primitive2dXmlDump::decomposeAndWrite( { const BitmapPrimitive2D& rBitmapPrimitive2D = dynamic_cast<const BitmapPrimitive2D&>(*pBasePrimitive); rWriter.startElement("bitmap"); - - basegfx::B2DHomMatrix const & rMatrix = rBitmapPrimitive2D.getTransform(); - rWriter.attribute("xy11", rMatrix.get(0,0)); - rWriter.attribute("xy12", rMatrix.get(0,1)); - rWriter.attribute("xy13", rMatrix.get(0,2)); - rWriter.attribute("xy21", rMatrix.get(1,0)); - rWriter.attribute("xy22", rMatrix.get(1,1)); - rWriter.attribute("xy23", rMatrix.get(1,2)); - rWriter.attribute("xy31", rMatrix.get(2,0)); - rWriter.attribute("xy32", rMatrix.get(2,1)); - rWriter.attribute("xy33", rMatrix.get(2,2)); + writeMatrix(rWriter, rBitmapPrimitive2D.getTransform()); const BitmapEx aBitmapEx(VCLUnoHelper::GetBitmap(rBitmapPrimitive2D.getXBitmap())); const Size& rSizePixel(aBitmapEx.GetSizePixel()); @@ -260,18 +265,7 @@ void Primitive2dXmlDump::decomposeAndWrite( { const TransformPrimitive2D& rTransformPrimitive2D = dynamic_cast<const TransformPrimitive2D&>(*pBasePrimitive); rWriter.startElement("transform"); - - basegfx::B2DHomMatrix const & rMatrix = rTransformPrimitive2D.getTransformation(); - rWriter.attributeDouble("xy11", rMatrix.get(0,0)); - rWriter.attributeDouble("xy12", rMatrix.get(0,1)); - rWriter.attributeDouble("xy13", rMatrix.get(0,2)); - rWriter.attributeDouble("xy21", rMatrix.get(1,0)); - rWriter.attributeDouble("xy22", rMatrix.get(1,1)); - rWriter.attributeDouble("xy23", rMatrix.get(1,2)); - rWriter.attributeDouble("xy31", rMatrix.get(2,0)); - rWriter.attributeDouble("xy32", rMatrix.get(2,1)); - rWriter.attributeDouble("xy33", rMatrix.get(2,2)); - + writeMatrix(rWriter, rTransformPrimitive2D.getTransformation()); decomposeAndWrite(rTransformPrimitive2D.getChildren(), rWriter); rWriter.endElement(); } @@ -355,7 +349,35 @@ void Primitive2dXmlDump::decomposeAndWrite( rWriter.content(basegfx::utils::exportToSvgPoints(rPolygonHairlinePrimitive2D.getB2DPolygon())); rWriter.endElement(); + rWriter.endElement(); + } + break; + case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D: + { + const TextDecoratedPortionPrimitive2D& rTextDecoratedPortionPrimitive2D = dynamic_cast<const TextDecoratedPortionPrimitive2D&>(*pBasePrimitive); + rWriter.startElement("textdecoratedportion"); + writeMatrix(rWriter, rTextDecoratedPortionPrimitive2D.getTextTransform()); + + rWriter.attribute("text", rTextDecoratedPortionPrimitive2D.getText()); + rWriter.attribute("fontcolor", convertColorToString(rTextDecoratedPortionPrimitive2D.getFontColor())); + + const drawinglayer::attribute::FontAttribute& aFontAttribute = rTextDecoratedPortionPrimitive2D.getFontAttribute(); + rWriter.attribute("familyname", aFontAttribute.getFamilyName()); + rWriter.endElement(); + } + break; + + case PRIMITIVE2D_ID_TEXTLINEPRIMITIVE2D: + { + const TextLinePrimitive2D& rTextLinePrimitive2D = dynamic_cast<const TextLinePrimitive2D&>(*pBasePrimitive); + rWriter.startElement("textline"); + writeMatrix(rWriter, rTextLinePrimitive2D.getObjectTransformation()); + + rWriter.attribute("width", rTextLinePrimitive2D.getWidth()); + rWriter.attribute("offset", rTextLinePrimitive2D.getOffset()); + rWriter.attribute("height", rTextLinePrimitive2D.getHeight()); + rWriter.attribute("color", convertColorToString(rTextLinePrimitive2D.getLineColor())); rWriter.endElement(); } break; @@ -406,9 +428,8 @@ void Primitive2dXmlDump::decomposeAndWrite( { const UnifiedTransparencePrimitive2D& rUnifiedTransparencePrimitive2D = dynamic_cast<const UnifiedTransparencePrimitive2D&>(*pBasePrimitive); rWriter.startElement("unifiedtransparence"); - rWriter.attribute("transparence", OString::number(rUnifiedTransparencePrimitive2D.getTransparence())); + rWriter.attribute("transparence", std::lround(100 * rUnifiedTransparencePrimitive2D.getTransparence())); decomposeAndWrite(rUnifiedTransparencePrimitive2D.getChildren(), rWriter); - rWriter.endElement(); } break; @@ -452,16 +473,7 @@ void Primitive2dXmlDump::decomposeAndWrite( rWriter.attributeDouble("opacity", rSvgLinearGradientPrimitive2D.getGradientEntries().front().getOpacity()); rWriter.startElement("transform"); - basegfx::B2DHomMatrix const & rMatrix = rSvgLinearGradientPrimitive2D.getGradientTransform(); - rWriter.attributeDouble("xy11", rMatrix.get(0,0)); - rWriter.attributeDouble("xy12", rMatrix.get(0,1)); - rWriter.attributeDouble("xy13", rMatrix.get(0,2)); - rWriter.attributeDouble("xy21", rMatrix.get(1,0)); - rWriter.attributeDouble("xy22", rMatrix.get(1,1)); - rWriter.attributeDouble("xy23", rMatrix.get(1,2)); - rWriter.attributeDouble("xy31", rMatrix.get(2,0)); - rWriter.attributeDouble("xy32", rMatrix.get(2,1)); - rWriter.attributeDouble("xy33", rMatrix.get(2,2)); + writeMatrix(rWriter, rSvgLinearGradientPrimitive2D.getGradientTransform()); rWriter.endElement(); writePolyPolygon(rWriter, rSvgLinearGradientPrimitive2D.getPolyPolygon()); |