vclmetafileprocessor2d.cxx (64b14621) vclmetafileprocessor2d.cxx (ff9ad81e)
1/**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance

--- 782 unchanged lines hidden (view full) ---

791 // svtools/source/graphic/grfmgr.cxx
792 const basegfx::B2DRange aCurrentRange(
793 aTranslate.getX(), aTranslate.getY(),
794 aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
795 const Rectangle aCurrentRect(
796 sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
797 sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
798 const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
1/**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance

--- 782 unchanged lines hidden (view full) ---

791 // svtools/source/graphic/grfmgr.cxx
792 const basegfx::B2DRange aCurrentRange(
793 aTranslate.getX(), aTranslate.getY(),
794 aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
795 const Rectangle aCurrentRect(
796 sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
797 sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
798 const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
799 Rectangle aCropRect;
800
799
800 // #123295# As described below this is the expanded, uncropped region
801 // and needs to be given in any case, especially when no cropping it is
802 // equal to the current rect. To make clear: normally the uncropped region
803 // (aka the aCropRect) is bigger than the CurrentRect. Or in other words:
804 // The current rect is the object area. This internal crop definition is
805 // somewhat crude, but used (and defined in graphic-dependent units what
806 // leads to even more problems, percentages would have been better). All
807 // in all this is a place that makes clear that a pure PDF export which does
808 // not use Metafile and the associated hacks (like this one) but is based on
809 // Primitves and uses a Primitive Renderer would be the better choice for
810 // the future.
811 Rectangle aCropRect(aCurrentRect);
812
801 if(rAttr.IsCropped())
802 {
803 // calculate scalings between real image size and logic object size. This
804 // is necessary since the crop values are relative to original bitmap size
805 double fFactorX(1.0);
806 double fFactorY(1.0);
807
808 {

--- 621 unchanged lines hidden (view full) ---

1430 // Do use decomposition; encapsulate with SvtGraphicFill
1431 impStartSvtGraphicFill(pSvtGraphicFill);
1432 process(rCandidate.get2DDecomposition(getViewInformation2D()));
1433 impEndSvtGraphicFill(pSvtGraphicFill);
1434 }
1435
1436 break;
1437 }
813 if(rAttr.IsCropped())
814 {
815 // calculate scalings between real image size and logic object size. This
816 // is necessary since the crop values are relative to original bitmap size
817 double fFactorX(1.0);
818 double fFactorY(1.0);
819
820 {

--- 621 unchanged lines hidden (view full) ---

1442 // Do use decomposition; encapsulate with SvtGraphicFill
1443 impStartSvtGraphicFill(pSvtGraphicFill);
1444 process(rCandidate.get2DDecomposition(getViewInformation2D()));
1445 impEndSvtGraphicFill(pSvtGraphicFill);
1446 }
1447
1448 break;
1449 }
1438 case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
1439 {
1440 // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
1441 const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
1442 const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
1443 basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
1450 case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
1451 {
1452 // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
1453 const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
1454 const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
1455 basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
1444
1456
1445 if(aLocalPolyPolygon.getB2DRange() != rHatchCandidate.getDefinitionRange())
1446 {
1447 // the range which defines the hatch is different from the range of the
1448 // geometry (used for writer frames). This cannot be done calling vcl, thus use
1449 // decomposition here
1450 process(rCandidate.get2DDecomposition(getViewInformation2D()));
1451 break;
1452 }
1453
1454 // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1455 // per polygon. Split polygon until there are less than that
1456 while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1457 ;
1458
1457 // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1458 // per polygon. Split polygon until there are less than that
1459 while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1460 ;
1461
1459 if(rFillHatchAttribute.isFillBackground())
1460 {
1461 // with fixing #i111954# (see below) the possible background
1462 // fill of a hatched object was lost.Generate a background fill
1463 // primitive and render it
1464 const primitive2d::Primitive2DReference xBackground(
1465 new primitive2d::PolyPolygonColorPrimitive2D(
1466 aLocalPolyPolygon,
1467 rHatchCandidate.getBackgroundColor()));
1468
1469 process(primitive2d::Primitive2DSequence(&xBackground, 1));
1470 }
1462 if(rFillHatchAttribute.isFillBackground())
1463 {
1464 // with fixing #i111954# (see below) the possible background
1465 // fill of a hatched object was lost.Generate a background fill
1466 // primitive and render it
1467 const primitive2d::Primitive2DReference xBackground(
1468 new primitive2d::PolyPolygonColorPrimitive2D(
1469 aLocalPolyPolygon,
1470 rHatchCandidate.getBackgroundColor()));
1471
1472 process(primitive2d::Primitive2DSequence(&xBackground, 1));
1473 }
1471
1472 SvtGraphicFill* pSvtGraphicFill = 0;
1474
1475 SvtGraphicFill* pSvtGraphicFill = 0;
1473 aLocalPolyPolygon.transform(maCurrentTransformation);
1476 aLocalPolyPolygon.transform(maCurrentTransformation);
1474
1477
1475 if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1476 {
1477 // re-create a VCL hatch as base data
1478 SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
1478 if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1479 {
1480 // re-create a VCL hatch as base data
1481 SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
1479
1482
1480 switch(rFillHatchAttribute.getStyle())
1481 {
1482 default: // attribute::HATCHSTYLE_SINGLE :
1483 {
1484 eHatch = SvtGraphicFill::hatchSingle;
1485 break;
1486 }
1487 case attribute::HATCHSTYLE_DOUBLE :
1488 {
1489 eHatch = SvtGraphicFill::hatchDouble;
1490 break;
1491 }
1492 case attribute::HATCHSTYLE_TRIPLE :
1493 {
1494 eHatch = SvtGraphicFill::hatchTriple;
1495 break;
1496 }
1497 }
1483 switch(rFillHatchAttribute.getStyle())
1484 {
1485 default: // attribute::HATCHSTYLE_SINGLE :
1486 {
1487 eHatch = SvtGraphicFill::hatchSingle;
1488 break;
1489 }
1490 case attribute::HATCHSTYLE_DOUBLE :
1491 {
1492 eHatch = SvtGraphicFill::hatchDouble;
1493 break;
1494 }
1495 case attribute::HATCHSTYLE_TRIPLE :
1496 {
1497 eHatch = SvtGraphicFill::hatchTriple;
1498 break;
1499 }
1500 }
1498
1501
1499 SvtGraphicFill::Transform aTransform;
1500
1501 // scale
1502 aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
1503 aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
1502 SvtGraphicFill::Transform aTransform;
1503
1504 // scale
1505 aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
1506 aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
1504
1507
1505 // rotate (was never correct in impgrfll anyways, use correct angle now)
1506 aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
1507 aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
1508 aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
1509 aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
1510
1511 pSvtGraphicFill = new SvtGraphicFill(
1512 PolyPolygon(aLocalPolyPolygon),
1513 Color(),
1514 0.0,
1515 SvtGraphicFill::fillEvenOdd,
1516 SvtGraphicFill::fillHatch,
1517 aTransform,
1518 false,
1519 eHatch,
1520 Color(rFillHatchAttribute.getColor()),
1521 SvtGraphicFill::gradientLinear,
1522 Color(),
1523 Color(),
1524 0,
1525 Graphic());
1526 }
1508 // rotate (was never correct in impgrfll anyways, use correct angle now)
1509 aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
1510 aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
1511 aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
1512 aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
1513
1514 pSvtGraphicFill = new SvtGraphicFill(
1515 PolyPolygon(aLocalPolyPolygon),
1516 Color(),
1517 0.0,
1518 SvtGraphicFill::fillEvenOdd,
1519 SvtGraphicFill::fillHatch,
1520 aTransform,
1521 false,
1522 eHatch,
1523 Color(rFillHatchAttribute.getColor()),
1524 SvtGraphicFill::gradientLinear,
1525 Color(),
1526 Color(),
1527 0,
1528 Graphic());
1529 }
1527
1530
1528 // Do use decomposition; encapsulate with SvtGraphicFill
1529 impStartSvtGraphicFill(pSvtGraphicFill);
1531 // Do use decomposition; encapsulate with SvtGraphicFill
1532 impStartSvtGraphicFill(pSvtGraphicFill);
1530
1531 // #i111954# do NOT use decomposition, but use direct VCL-command
1533
1534 // #i111954# do NOT use decomposition, but use direct VCL-command
1532 // process(rCandidate.get2DDecomposition(getViewInformation2D()));
1533 const PolyPolygon aToolsPolyPolygon(aLocalPolyPolygon);
1535 // process(rCandidate.get2DDecomposition(getViewInformation2D()));
1536 const PolyPolygon aToolsPolyPolygon(aLocalPolyPolygon);
1534 const HatchStyle aHatchStyle(
1535 attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE :
1536 attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE :
1537 HATCH_TRIPLE);
1538
1539 mpOutputDevice->DrawHatch(aToolsPolyPolygon,
1540 Hatch(aHatchStyle,
1541 Color(rFillHatchAttribute.getColor()),
1542 basegfx::fround(rFillHatchAttribute.getDistance()),
1543 basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
1544
1545 impEndSvtGraphicFill(pSvtGraphicFill);
1546
1537 const HatchStyle aHatchStyle(
1538 attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE :
1539 attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE :
1540 HATCH_TRIPLE);
1541
1542 mpOutputDevice->DrawHatch(aToolsPolyPolygon,
1543 Hatch(aHatchStyle,
1544 Color(rFillHatchAttribute.getColor()),
1545 basegfx::fround(rFillHatchAttribute.getDistance()),
1546 basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
1547
1548 impEndSvtGraphicFill(pSvtGraphicFill);
1549
1547 break;
1548 }
1549 case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
1550 break;
1551 }
1552 case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
1550 {
1551 basegfx::B2DVector aScale, aTranslate;
1552 double fRotate, fShearX;
1553
1554 maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
1555
1556 if(!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX))
1557 {

--- 10 unchanged lines hidden (view full) ---

1568 // These will need more space and time, but the result will be as if the Gradient
1569 // was rotated with the object.
1570 // This mechanism is used by all exporters still not using Primtives (e.g. Print,
1571 // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile
1572 // transfers. One more reason to *change* these to primitives.
1573 // BTW: One more example how useful the principles of primitives are; the decomposition
1574 // is by definition a simpler, maybe more expensive representation of the same content.
1575 process(rCandidate.get2DDecomposition(getViewInformation2D()));
1553 {
1554 basegfx::B2DVector aScale, aTranslate;
1555 double fRotate, fShearX;
1556
1557 maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
1558
1559 if(!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX))
1560 {

--- 10 unchanged lines hidden (view full) ---

1571 // These will need more space and time, but the result will be as if the Gradient
1572 // was rotated with the object.
1573 // This mechanism is used by all exporters still not using Primtives (e.g. Print,
1574 // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile
1575 // transfers. One more reason to *change* these to primitives.
1576 // BTW: One more example how useful the principles of primitives are; the decomposition
1577 // is by definition a simpler, maybe more expensive representation of the same content.
1578 process(rCandidate.get2DDecomposition(getViewInformation2D()));
1576 break;
1577 }
1579 }
1578
1579 const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
1580 basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
1581
1582 if(aLocalPolyPolygon.getB2DRange() != rGradientCandidate.getDefinitionRange())
1580 else
1583 {
1581 {
1584 // the range which defines the gradient is different from the range of the
1585 // geometry (used for writer frames). This cannot be done calling vcl, thus use
1586 // decomposition here
1587 process(rCandidate.get2DDecomposition(getViewInformation2D()));
1588 break;
1589 }
1582 const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
1583 basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
1590
1584
1591 // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1592 // per polygon. Split polygon until there are less than that
1593 while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1594 ;
1585 // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1586 // per polygon. Split polygon until there are less than that
1587 while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1588 ;
1595
1589
1596 // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END
1597 // it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
1598 // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
1599 Gradient aVCLGradient;
1600 impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false);
1601 aLocalPolyPolygon.transform(maCurrentTransformation);
1590 // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END
1591 // it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
1592 // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
1593 Gradient aVCLGradient;
1594 impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false);
1595 aLocalPolyPolygon.transform(maCurrentTransformation);
1602
1596
1603 // #i82145# ATM VCL printing of gradients using curved shapes does not work,
1604 // i submitted the bug with the given ID to THB. When that task is fixed it is
1605 // necessary to again remove this subdivision since it decreases possible
1606 // printing quality (not even resolution-dependent for now). THB will tell
1607 // me when that task is fixed in the master
1608 const PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon));
1597 // #i82145# ATM VCL printing of gradients using curved shapes does not work,
1598 // i submitted the bug with the given ID to THB. When that task is fixed it is
1599 // necessary to again remove this subdivision since it decreases possible
1600 // printing quality (not even resolution-dependent for now). THB will tell
1601 // me when that task is fixed in the master
1602 const PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon));
1609
1603
1610 // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1611 SvtGraphicFill* pSvtGraphicFill = 0;
1604 // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1605 SvtGraphicFill* pSvtGraphicFill = 0;
1612
1606
1613 if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1614 {
1615 // setup gradient stuff like in like in impgrfll
1616 SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear);
1607 if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1608 {
1609 // setup gradient stuff like in like in impgrfll
1610 SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear);
1617
1611
1618 switch(aVCLGradient.GetStyle())
1619 {
1620 default : // GRADIENT_LINEAR:
1621 case GRADIENT_AXIAL:
1622 eGrad = SvtGraphicFill::gradientLinear;
1623 break;
1624 case GRADIENT_RADIAL:
1625 case GRADIENT_ELLIPTICAL:
1626 eGrad = SvtGraphicFill::gradientRadial;
1627 break;
1628 case GRADIENT_SQUARE:
1629 case GRADIENT_RECT:
1630 eGrad = SvtGraphicFill::gradientRectangular;
1631 break;
1632 }
1633
1634 pSvtGraphicFill = new SvtGraphicFill(
1635 aToolsPolyPolygon,
1636 Color(),
1637 0.0,
1638 SvtGraphicFill::fillEvenOdd,
1639 SvtGraphicFill::fillGradient,
1640 SvtGraphicFill::Transform(),
1641 false,
1642 SvtGraphicFill::hatchSingle,
1643 Color(),
1644 eGrad,
1645 aVCLGradient.GetStartColor(),
1646 aVCLGradient.GetEndColor(),
1647 aVCLGradient.GetSteps(),
1648 Graphic());
1612 switch(aVCLGradient.GetStyle())
1613 {
1614 default : // GRADIENT_LINEAR:
1615 case GRADIENT_AXIAL:
1616 eGrad = SvtGraphicFill::gradientLinear;
1617 break;
1618 case GRADIENT_RADIAL:
1619 case GRADIENT_ELLIPTICAL:
1620 eGrad = SvtGraphicFill::gradientRadial;
1621 break;
1622 case GRADIENT_SQUARE:
1623 case GRADIENT_RECT:
1624 eGrad = SvtGraphicFill::gradientRectangular;
1625 break;
1626 }
1627
1628 pSvtGraphicFill = new SvtGraphicFill(
1629 aToolsPolyPolygon,
1630 Color(),
1631 0.0,
1632 SvtGraphicFill::fillEvenOdd,
1633 SvtGraphicFill::fillGradient,
1634 SvtGraphicFill::Transform(),
1635 false,
1636 SvtGraphicFill::hatchSingle,
1637 Color(),
1638 eGrad,
1639 aVCLGradient.GetStartColor(),
1640 aVCLGradient.GetEndColor(),
1641 aVCLGradient.GetSteps(),
1642 Graphic());
1643 }
1644
1645 // call VCL directly; encapsulate with SvtGraphicFill
1646 impStartSvtGraphicFill(pSvtGraphicFill);
1647 mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
1648 impEndSvtGraphicFill(pSvtGraphicFill);
1649 }
1650
1649 }
1650
1651 // call VCL directly; encapsulate with SvtGraphicFill
1652 impStartSvtGraphicFill(pSvtGraphicFill);
1653 mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
1654 impEndSvtGraphicFill(pSvtGraphicFill);
1655
1656 break;
1657 }
1658 case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
1659 {
1660 const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
1661 basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
1662
1663 // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points

--- 491 unchanged lines hidden ---
1651 break;
1652 }
1653 case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
1654 {
1655 const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
1656 basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
1657
1658 // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points

--- 491 unchanged lines hidden ---