/* -*- 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 .
*/
bool GeoTexSvx::operator==(const GeoTexSvx& /*rGeoTexSvx*/) const
{ // default implementation says yes (no data -> no difference) returntrue;
}
void GeoTexSvx::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{ // base implementation creates random color (for testing only, may also be pure virtual)
rBColor.setRed(getRandomColorRange());
rBColor.setGreen(getRandomColorRange());
rBColor.setBlue(getRandomColorRange());
}
void GeoTexSvx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
{ // base implementation uses inverse of luminance of solved color (for testing only, may also be pure virtual)
basegfx::BColor aBaseColor;
modifyBColor(rUV, aBaseColor, rfOpacity);
rfOpacity = 1.0 - aBaseColor.luminance();
}
void GeoTexSvxGradientLinear::appendTransformationsAndColors( const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{ // no color at all, done if (mnColorStops.empty()) return;
// only one color, done if (mnColorStops.size() < 2) return;
// check if we need last-ColorStop-correction constbool bPenultimateUsed(mnColorStops.checkPenultimate());
if (bPenultimateUsed)
{ // Here we need to temporarily add a ColorStop entry with the // same color as the last entry to correctly 'close' the // created gradient geometry. // The simplest way is to temporarily add an entry to the local // ColorStops for this at 1.0 (using same color)
mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
}
// prepare unit range transform
basegfx::B2DHomMatrix aPattern;
// bring from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1]
aPattern.scale(0.5, 0.5);
aPattern.translate(0.5, 0.5);
// scale and translate in X
aPattern.scale(mfUnitWidth, 1.0);
aPattern.translate(mfUnitMinX, 0.0);
// outer loop over ColorStops, each is from cs_l to cs_r for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{ // get offsets constdouble fOffsetStart(cs_l->getStopOffset()); constdouble fOffsetEnd(cs_r->getStopOffset());
// same offset, empty BColorStopRange, continue with next step if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd)) continue;
// calculate StripeWidth // nSteps is >= 1, see getRequestedSteps, so no check needed here constdouble fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
// for the 1st color range we do not need to create the 1st step // since it will be equal to StartColor and thus OuterColor, so // will be painted by the 1st, always-created background polygon // colored using OuterColor. // We *need* to create this though for all 'inner' color ranges // to get a correct start const sal_uInt32 nStartInnerLoop(cs_l == mnColorStops.begin() ? 1 : 0);
for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
{ // calculate pos in Y constdouble fPos(fOffsetStart + (fStripeWidth * innerLoop));
// scale and translate in Y. For GradientLinear we always have // the full height double fHeight(1.0 - fPos);
if (mfUnitMaxY > 1.0)
{ // extend when difference between definition and OutputRange exists
fHeight += mfUnitMaxY - 1.0;
}
// set and add at target
rCallback(
maGradientInfo.getTextureTransform() * aNew,
1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
}
}
if (bPenultimateUsed)
{ // correct temporary change
mnColorStops.pop_back();
}
}
void GeoTexSvxGradientLinear::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{ // no color at all, done if (mnColorStops.empty()) return;
// just single color, done if (mnColorStops.size() < 2)
{
rBColor = mnColorStops.front().getStopColor(); return;
}
// texture-back-transform X/Y -> t [0.0..1.0] and determine color constdouble fScaler(basegfx::utils::getLinearGradientAlpha(rUV, maGradientInfo));
rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
GeoTexSvxGradientAxial::GeoTexSvxGradientAxial( const basegfx::B2DRange& rDefinitionRange, const basegfx::B2DRange& rOutputRange,
sal_uInt32 nRequestedSteps, const basegfx::BColorStops& rColorStops, double fBorder, double fAngle)
: GeoTexSvxGradient(rDefinitionRange, nRequestedSteps, rColorStops, fBorder)
, mfUnitMinX(0.0)
, mfUnitWidth(1.0)
{ // ARGH! GradientAxial uses the ColorStops in reverse order compared // with the other gradients. Either stay 'thinking reverse' for the // rest of time or adapt it here and go in same order as the other five, // so unifications/tooling will be possible
mnColorStops.reverseColorStops();
void GeoTexSvxGradientAxial::appendTransformationsAndColors( const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{ // no color at all, done if (mnColorStops.empty()) return;
// only one color, done if (mnColorStops.size() < 2) return;
// check if we need last-ColorStop-correction constbool bPenultimateUsed(mnColorStops.checkPenultimate());
if (bPenultimateUsed)
{ // temporarily add a ColorStop entry
mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
}
// prepare unit range transform
basegfx::B2DHomMatrix aPattern;
// bring in X from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1]
aPattern.scale(0.5, 1.0);
aPattern.translate(0.5, 0.0);
// scale/translate in X
aPattern.scale(mfUnitWidth, 1.0);
aPattern.translate(mfUnitMinX, 0.0);
// outer loop over ColorStops, each is from cs_l to cs_r for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{ // get offsets constdouble fOffsetStart(cs_l->getStopOffset()); constdouble fOffsetEnd(cs_r->getStopOffset());
// same offset, empty BColorStopRange, continue with next step if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd)) continue;
// calculate StripeWidth // nSteps is >= 1, see getRequestedSteps, so no check needed here constdouble fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
// for the 1st color range we do not need to create the 1st step, see above const sal_uInt32 nStartInnerLoop(cs_l == mnColorStops.begin() ? 1 : 0);
for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
{ // calculate pos in Y constdouble fPos(fOffsetStart + (fStripeWidth * innerLoop));
// already centered in Y on X-Axis, just scale in Y
basegfx::B2DHomMatrix aNew(aPattern);
aNew.scale(1.0, 1.0 - fPos);
// set and add at target
rCallback(
maGradientInfo.getTextureTransform() * aNew,
1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
}
}
if (bPenultimateUsed)
{ // correct temporary change
mnColorStops.pop_back();
}
}
void GeoTexSvxGradientAxial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{ // no color at all, done if (mnColorStops.empty()) return;
// just single color, done if (mnColorStops.size() < 2)
{ // we use the reverse ColorSteps here, so use front value
rBColor = mnColorStops.front().getStopColor(); return;
}
// texture-back-transform X/Y -> t [0.0..1.0] and determine color constdouble fScaler(basegfx::utils::getAxialGradientAlpha(rUV, maGradientInfo));
// we use the reverse ColorSteps here, so mirror scaler value
rBColor = mnColorStops.getInterpolatedBColor(1.0 - fScaler, mnRequestedSteps, maLastColorStopRange);
}
void GeoTexSvxGradientRadial::appendTransformationsAndColors( const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{ // no color at all, done if (mnColorStops.empty()) return;
// only one color, done if (mnColorStops.size() < 2) return;
// check if we need last-ColorStop-correction constbool bPenultimateUsed(mnColorStops.checkPenultimate());
if (bPenultimateUsed)
{ // temporarily add a ColorStop entry
mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
}
// outer loop over ColorStops, each is from cs_l to cs_r for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{ // get offsets constdouble fOffsetStart(cs_l->getStopOffset()); constdouble fOffsetEnd(cs_r->getStopOffset());
// same offset, empty BColorStopRange, continue with next step if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd)) continue;
// set and add at target
rCallback(
maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize),
1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
}
}
if (bPenultimateUsed)
{ // correct temporary change
mnColorStops.pop_back();
}
}
void GeoTexSvxGradientRadial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{ // no color at all, done if (mnColorStops.empty()) return;
// just single color, done if (mnColorStops.size() < 2)
{
rBColor = mnColorStops.front().getStopColor(); return;
}
// texture-back-transform X/Y -> t [0.0..1.0] and determine color constdouble fScaler(basegfx::utils::getRadialGradientAlpha(rUV, maGradientInfo));
rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
void GeoTexSvxGradientElliptical::appendTransformationsAndColors( const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{ // no color at all, done if (mnColorStops.empty()) return;
// only one color, done if (mnColorStops.size() < 2) return;
// check if we need last-ColorStop-correction constbool bPenultimateUsed(mnColorStops.checkPenultimate());
if (bPenultimateUsed)
{ // temporarily add a ColorStop entry
mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
}
// prepare vars dependent on aspect ratio constdouble fAR(maGradientInfo.getAspectRatio()); constbool bMTO(fAR > 1.0);
// outer loop over ColorStops, each is from cs_l to cs_r for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{ // get offsets constdouble fOffsetStart(cs_l->getStopOffset()); constdouble fOffsetEnd(cs_r->getStopOffset());
// same offset, empty BColorStopRange, continue with next step if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd)) continue;
if (bPenultimateUsed)
{ // correct temporary change
mnColorStops.pop_back();
}
}
void GeoTexSvxGradientElliptical::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{ // no color at all, done if (mnColorStops.empty()) return;
// just single color, done if (mnColorStops.size() < 2)
{
rBColor = mnColorStops.front().getStopColor(); return;
}
// texture-back-transform X/Y -> t [0.0..1.0] and determine color constdouble fScaler(basegfx::utils::getEllipticalGradientAlpha(rUV, maGradientInfo));
rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
void GeoTexSvxGradientSquare::appendTransformationsAndColors( const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{ // no color at all, done if (mnColorStops.empty()) return;
// only one color, done if (mnColorStops.size() < 2) return;
// check if we need last-ColorStop-correction constbool bPenultimateUsed(mnColorStops.checkPenultimate());
if (bPenultimateUsed)
{ // temporarily add a ColorStop entry
mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
}
// outer loop over ColorStops, each is from cs_l to cs_r for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{ // get offsets constdouble fOffsetStart(cs_l->getStopOffset()); constdouble fOffsetEnd(cs_r->getStopOffset());
// same offset, empty BColorStopRange, continue with next step if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd)) continue;
// set and add at target
rCallback(
maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize),
1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
}
}
if (bPenultimateUsed)
{ // correct temporary change
mnColorStops.pop_back();
}
}
void GeoTexSvxGradientSquare::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{ // no color at all, done if (mnColorStops.empty()) return;
// just single color, done if (mnColorStops.size() < 2)
{
rBColor = mnColorStops.front().getStopColor(); return;
}
// texture-back-transform X/Y -> t [0.0..1.0] and determine color constdouble fScaler(basegfx::utils::getSquareGradientAlpha(rUV, maGradientInfo));
rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
void GeoTexSvxGradientRect::appendTransformationsAndColors( const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{ // no color at all, done if (mnColorStops.empty()) return;
// only one color, done if (mnColorStops.size() < 2) return;
// check if we need last-ColorStop-correction constbool bPenultimateUsed(mnColorStops.checkPenultimate());
if (bPenultimateUsed)
{ // temporarily add a ColorStop entry
mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
}
// prepare vars dependent on aspect ratio constdouble fAR(maGradientInfo.getAspectRatio()); constbool bMTO(fAR > 1.0);
// outer loop over ColorStops, each is from cs_l to cs_r for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{ // get offsets constdouble fOffsetStart(cs_l->getStopOffset()); constdouble fOffsetEnd(cs_r->getStopOffset());
// same offset, empty BColorStopRange, continue with next step if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd)) continue;
if (bPenultimateUsed)
{ // correct temporary change
mnColorStops.pop_back();
}
}
void GeoTexSvxGradientRect::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{ // no color at all, done if (mnColorStops.empty()) return;
// just single color, done if (mnColorStops.size() < 2)
{
rBColor = mnColorStops.front().getStopColor(); return;
}
// texture-back-transform X/Y -> t [0.0..1.0] and determine color constdouble fScaler(basegfx::utils::getRectangularGradientAlpha(rUV, maGradientInfo));
rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
void GeoTexSvxHatch::appendTransformations(std::vector< basegfx::B2DHomMatrix >& rMatrices)
{ if(mbDefinitionRangeEqualsOutputRange)
{ // simple hatch where the definition area equals the output area for(sal_uInt32 a(1); a < mnSteps; a++)
{ // create matrix constdouble fOffset(mfDistance * static_cast<double>(a));
basegfx::B2DHomMatrix aNew;
aNew.set(1, 2, fOffset);
rMatrices.push_back(maTextureTransform * aNew);
}
} else
{ // output area is different from definition area, back-transform to get // the output area in unit coordinates and fill this with hatch lines // using the settings derived from the definition area
basegfx::B2DRange aBackUnitRange(maOutputRange);
// calculate vertical start value and a security maximum integer value to avoid death loops double fStart(basegfx::snapToNearestMultiple(aBackUnitRange.getMinY(), mfDistance)); const sal_uInt32 nNeededIntegerSteps(basegfx::fround((aBackUnitRange.getHeight() / mfDistance) + 0.5));
sal_uInt32 nMaxIntegerSteps(std::min(nNeededIntegerSteps, sal_uInt32(10000)));
while(fStart < aBackUnitRange.getMaxY() && nMaxIntegerSteps)
{ // create new transform for
basegfx::B2DHomMatrix aNew;
// adapt x scale and position //aNew.scale(aBackUnitRange.getWidth(), 1.0); //aNew.translate(aBackUnitRange.getMinX(), 0.0);
aNew.set(0, 0, aBackUnitRange.getWidth());
aNew.set(0, 2, aBackUnitRange.getMinX());
// adapt y position to current step
aNew.set(1, 2, fStart); //aNew.translate(0.0, fStart);
// add new transformation
rMatrices.push_back(maTextureTransform * aNew);
// next step
fStart += mfDistance;
nMaxIntegerSteps--;
}
}
}
double GeoTexSvxHatch::getDistanceToHatch(const basegfx::B2DPoint& rUV) const
{ // the below is an inlined and optimised version of // const basegfx::B2DPoint aCoor(getBackTextureTransform() * rUV); // return fmod(aCoor.getY(), mfDistance);
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.