/* -*- 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 .
*/
/** Most of the setup for linear & axial gradient is the same, except for the border treatment. Factored out here.
*/ static ODFGradientInfo init1DGradientInfo( const B2DRange& rTargetRange,
sal_uInt32 nSteps, double fBorder, double fAngle, bool bAxial)
{
B2DHomMatrix aTextureTransform;
/** Most of the setup for radial & ellipsoidal gradient is the same, except for the border treatment. Factored out here.
*/ static ODFGradientInfo initEllipticalGradientInfo( const B2DRange& rTargetRange, const B2DVector& rOffset,
sal_uInt32 nSteps, double fBorder, double fAngle, bool bCircular)
{
B2DHomMatrix aTextureTransform;
namespace utils
{ /* Tooling method to extract data from given BGradient to ColorStops, doing some corrections, partially based
on given SingleColor */ void prepareColorStops( const basegfx::BGradient& rGradient,
BColorStops& rColorStops,
BColor& rSingleColor)
{ if (rGradient.GetColorStops().isSingleColor(rSingleColor))
{ // when single color, preserve value in rSingleColor // and clear the ColorStops, done.
rColorStops.clear(); return;
}
// prepare a copy to work on
basegfx::BGradient aWorkCopy(rGradient);
if (bAdaptStartEndIntensity)
{
aWorkCopy.tryToApplyStartEndIntensity();
// this can again lead to single color (e.g. both zero, so // all black), so check again for it if (aWorkCopy.GetColorStops().isSingleColor(rSingleColor))
{
rColorStops.clear(); return;
}
}
if (bAdaptBorder)
{
aWorkCopy.tryToApplyBorder();
}
// extract ColorStops, that's all we need here
rColorStops = aWorkCopy.GetColorStops();
}
/* Tooling method to synchronize the given ColorStops. The intention is that a color GradientStops and an alpha/transparence GradientStops gets synchronized
for export. */ void synchronizeColorStops(
BColorStops& rColorStops,
BColorStops& rAlphaStops, const BColor& rSingleColor, const BColor& rSingleAlpha)
{ if (rColorStops.empty())
{ if (rAlphaStops.empty())
{ // no AlphaStops and no ColorStops // create two-stop fallbacks for both
rColorStops = BColorStops {
BColorStop(0.0, rSingleColor),
BColorStop(1.0, rSingleColor) };
rAlphaStops = BColorStops {
BColorStop(0.0, rSingleAlpha),
BColorStop(1.0, rSingleAlpha) };
} else
{ // AlphaStops but no ColorStops // create fallback synched with existing AlphaStops for (constauto& cand : rAlphaStops)
{
rColorStops.emplace_back(cand.getStopOffset(), rSingleColor);
}
}
// preparations complete, we are done return;
} elseif (rAlphaStops.empty())
{ // ColorStops but no AlphaStops // create fallback AlphaStops synched with existing ColorStops using SingleAlpha for (constauto& cand : rColorStops)
{
rAlphaStops.emplace_back(cand.getStopOffset(), rSingleAlpha);
}
// preparations complete, we are done return;
}
// here we have ColorStops and AlphaStops not empty. Check if we need to // synchronize both or if they are already usable/in a synched state so // that they have same count and same StopOffsets bool bNeedToSyncronize(rColorStops.size() != rAlphaStops.size());
if (!bNeedToSyncronize)
{ // check for same StopOffsets
BColorStops::const_iterator aCurrColor(rColorStops.begin());
BColorStops::const_iterator aCurrAlpha(rAlphaStops.begin());
if (bRealChange)
{ // copy on 'real' change, that means data was added. // This should always be the cease and should have been // detected as such above, see bNeedToSyncronize
rColorStops = std::move(aNewColor);
rAlphaStops = std::move(aNewAlpha); // MCGR: tdf#155537 used wrong result here
}
}
}
// MCGR: Similar to getRectangularGradientAlpha (please // see there) we need to use aspect ratio here. Due to // initEllipticalGradientInfo using M_SQRT2 to make this // gradient look 'nicer' this correction seems not 100% // correct, but is close enough for now if(fAspectRatio > 1.0)
{
t = 1.0 - std::hypot(aCoor.getX() / fAspectRatio, aCoor.getY());
} elseif(fAspectRatio > 0.0)
{
t = 1.0 - std::hypot(aCoor.getX(), aCoor.getY() * fAspectRatio);
}
// MCGR: Visualizations using the texturing method for // displaying gradients (getBackTextureTransform is // involved) show wrong results for GradientElliptical // and GradientRect, this can be best seen when using // less steps, e.g. just four. This thus has influence // on cppcanvas (slideshow) and 3D textures, so needs // to be corrected. // Missing is to use the aspect ratio of the object // in this [-1, -1, 1, 1] unified coordinate space // after getBackTextureTransform is applied. Optically // in the larger direction of the texturing the color // step distances are too big *because* we are in that // unit range now. // To correct that, a kind of 'limo stretching' needs to // be applied, adding space around the center // proportional to the aspect ratio, so the intuitive // idea would be to do // // fAbsX' = ((fAspectRatio - 1) + fAbsX) / fAspectRatio // // which scales from the center. This does not work, and // after some thoughts it's clear why: It's not the // position that needs to be moved (this cannot be // changed), but the position *before* that scale has // to be determined to get the correct, shifted color // for the already 'new' position. Thus, turn around // the expression as // // fAbsX' * fAspectRatio = fAspectRatio - 1 + fAbsX // fAbsX' * fAspectRatio - fAspectRatio + 1 = fAbsX // fAbsX = (fAbsX' - 1) * fAspectRatio + 1 // // This works and can even be simply adapted for // fAspectRatio < 1.0 aka vertical is bigger. double fAspectRatio(rGradInfo.getAspectRatio()); if(fAspectRatio > 1.0)
{
fAbsX = ((fAbsX - 1) * fAspectRatio) + 1;
} elseif(fAspectRatio > 0.0)
{
fAbsY = ((fAbsY - 1) / fAspectRatio) + 1;
}
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.