Commit 9d5baac8 authored by Agata Cacko's avatar Agata Cacko

Refactor KoUnit

Summary:
This commit fixes two problems in KoUnit:
(1) two functions named differently while doing
nearly exactly the same thing (ptToUnit, toUserValue)
and the difference in the name or arguments of functions
not showing the difference in the results,
(2) repeated constant values in functions
called to[Unit] (i.e. toMillimeters).
This commit is not to cause any difference in behaviour
(including in particular converting and rounding values)
and contains unit tests to test that.

Test Plan:
- created unit test to test the difference in conversions
(should not none).
- all the places where the difference in functions naming
caused changes in files other than [Test]KoUnit.h/.cpp

Reviewers: #krita, rempt

Reviewed By: #krita, rempt

Subscribers: rempt

Tags: #krita

Differential Revision: https://phabricator.kde.org/D19537
parent e3c5a596
......@@ -235,7 +235,7 @@ void KoOdfWorkaround::fixGluePointPosition(QString &positionString, KoShapeLoadi
KoOdfLoadingContext::GeneratorType type(context.odfLoadingContext().generatorType());
if (type == KoOdfLoadingContext::OpenOffice && !positionString.endsWith('%')) {
const qreal pos = KoUnit::parseValue(positionString);
positionString = QString("%1%%").arg(KoUnit::toMillimeter(pos));
positionString = QString("%1%%").arg(KoUnit(KoUnit::Millimeter).toUserValue(pos));
}
}
......
......@@ -135,32 +135,46 @@ int KoUnit::indexInListForUi(ListOptions listOptions) const
return result;
}
qreal KoUnit::toUserValue(qreal ptValue) const
qreal KoUnit::toUserValueRounded(const qreal value) const
{
qreal userValue = toUserValuePrecise(value);
qreal rounding = 1.0;
switch (m_type) {
case Pixel:
return userValue; // no rounding for Pixel value
case Millimeter:
return toMillimeter(ptValue);
rounding = MM_ROUNDING;
break;
case Centimeter:
return toCentimeter(ptValue);
rounding = CM_ROUNDING;
break;
case Decimeter:
return toDecimeter(ptValue);
rounding = DM_ROUNDING;
break;
case Inch:
return toInch(ptValue);
rounding = IN_ROUNDING;
break;
case Pica:
return toPica(ptValue);
rounding = PI_ROUNDING;
break;
case Cicero:
return toCicero(ptValue);
case Pixel:
return ptValue * m_pixelConversion;
rounding = CC_ROUNDING;
break;
case Point:
default:
return toPoint(ptValue);
rounding = PT_ROUNDING;
}
return floor(userValue * rounding) / rounding;
}
qreal KoUnit::ptToUnit(const qreal ptValue, const KoUnit &unit)
qreal KoUnit::toUserValuePrecise(const qreal ptValue) const
{
switch (unit.m_type) {
switch (m_type) {
case Millimeter:
return POINT_TO_MM(ptValue);
case Centimeter:
......@@ -174,13 +188,25 @@ qreal KoUnit::ptToUnit(const qreal ptValue, const KoUnit &unit)
case Cicero:
return POINT_TO_CC(ptValue);
case Pixel:
return ptValue * unit.m_pixelConversion;
return ptValue * m_pixelConversion;
case Point:
default:
return ptValue;
}
}
qreal KoUnit::toUserValue(qreal ptValue, bool rounding) const
{
if (rounding) {
return toUserValueRounded(ptValue);
}
else {
return toUserValuePrecise(ptValue);
}
}
QString KoUnit::toUserStringValue(qreal ptValue) const
{
return QLocale().toString(toUserValue(ptValue));
......
......@@ -56,6 +56,20 @@ constexpr qreal POINT_TO_CC(qreal px) {return (px)*0.077880997;}
constexpr qreal PI_TO_POINT(qreal pi) {return (pi)*12;}
constexpr qreal CC_TO_POINT(qreal cc) {return (cc)*12.840103;}
static const qreal PT_ROUNDING {1000.0};
//static const qreal PX_ROUNDING {1000.0}; // pixel value is not to be rounded
static const qreal CM_ROUNDING {10000.0};
static const qreal DM_ROUNDING {10000.0};
static const qreal MM_ROUNDING {10000.0};
static const qreal IN_ROUNDING {100000.0};
static const qreal PI_ROUNDING {100000.0}; // pico
static const qreal CC_ROUNDING {100000.0}; // cicero
/**
* %Calligra stores everything in pt (using "qreal") internally.
* When displaying a value to the user, the value is converted to the user's unit
......@@ -125,85 +139,35 @@ public:
void setFactor(qreal factor) {
m_pixelConversion = factor;
}
/**
* Prepare ptValue to be displayed in pt
* This method will round to 0.001 precision
*/
static qreal toPoint(qreal ptValue) {
// No conversion, only rounding (to 0.001 precision)
return floor(ptValue * 1000.0) / 1000.0;
}
/**
* Prepare ptValue to be displayed in mm
* This method will round to 0.0001 precision, use POINT_TO_MM() for lossless conversion.
*/
static qreal toMillimeter(qreal ptValue) {
// "mm" values are rounded to 0.0001 millimeters
return floor(POINT_TO_MM(ptValue) * 10000.0) / 10000.0;
}
/**
* Prepare ptValue to be displayed in cm
* This method will round to 0.0001 precision, use POINT_TO_CM() for lossless conversion.
*/
static qreal toCentimeter(qreal ptValue) {
return floor(POINT_TO_CM(ptValue) * 10000.0) / 10000.0;
}
/**
* Prepare ptValue to be displayed in dm
* This method will round to 0.0001 precision, use POINT_TO_DM() for lossless conversion.
*/
static qreal toDecimeter(qreal ptValue) {
return floor(POINT_TO_DM(ptValue) * 10000.0) / 10000.0;
}
/**
* Prepare ptValue to be displayed in inch
* This method will round to 0.00001 precision, use POINT_TO_INCH() for lossless conversion.
* convert the given value directly from one unit to another
*/
static qreal toInch(qreal ptValue) {
// "in" values are rounded to 0.00001 inches
return floor(POINT_TO_INCH(ptValue) * 100000.0) / 100000.0;
}
static qreal convertFromUnitToUnit(const qreal value, const KoUnit &fromUnit, const KoUnit &toUnit, qreal factor = 1.0);
/**
* Prepare ptValue to be displayed in pica
* This method will round to 0.00001 precision, use POINT_TO_PI() for lossless conversion.
* Convert the value @p ptValue to the unit and round it.
* This method is meant to be used to display a value in a dialog.
* \return the converted and rounded value
*/
static qreal toPica(qreal ptValue) {
// "pi" values are rounded to 0.00001 inches
return floor(POINT_TO_PI(ptValue) * 100000.0) / 100000.0;
}
qreal toUserValueRounded(const qreal value) const;
/**
* Prepare ptValue to be displayed in cicero
* This method will round to 0.00001 precision, use POINT_TO_CC() for lossless conversion.
* Convert the value @p ptValue to the unit (without rounding)
* This method is meant to be used in complex calculations.
* \return the converted value
*/
static qreal toCicero(qreal ptValue) {
// "cc" values are rounded to 0.00001 inches
return floor(POINT_TO_CC(ptValue) * 100000.0) / 100000.0;
}
qreal toUserValuePrecise(const qreal ptValue) const;
/**
* convert the given value directly from one unit to another
* Convert the value @p ptValue with or with rounding as indicated by @p rounding.
* This method is a proxy to toUserValuePrecise and toUserValueRounded.
* \return the value @p ptValue converted to unit
*/
static qreal convertFromUnitToUnit(const qreal value, const KoUnit &fromUnit, const KoUnit &toUnit, qreal factor = 1.0);
qreal toUserValue(qreal ptValue, bool rounding = true) const;
/**
* This method is the one to use to display a value in a dialog
* \return the value @p ptValue converted to unit and rounded, ready to be displayed
*/
qreal toUserValue(qreal ptValue) const;
/**
* Convert the value @p ptValue to a given unit @p unit
* Unlike KoUnit::ptToUnit the return value remains unrounded, so that it can be used in complex calculation
* \return the converted value
*/
static qreal ptToUnit(const qreal ptValue, const KoUnit &unit);
/// This method is the one to use to display a value in a dialog
/// @return the value @p ptValue converted the unit and rounded, ready to be displayed
......
......@@ -59,7 +59,7 @@ void TestKoUnit::testPixelConstructor()
{
KoUnit unit(KoUnit::Pixel, 0.5);
QCOMPARE(unit.type(), KoUnit::Pixel);
QCOMPARE(KoUnit::ptToUnit(100, unit), (qreal)50);
QCOMPARE(unit.toUserValue(100, false), (qreal)50);
}
void TestKoUnit::testAssignOperator_data()
......@@ -159,4 +159,54 @@ void TestKoUnit::testListForUi()
QCOMPARE(unit.indexInListForUi(listOptions), index);
}
void TestKoUnit::testToUserValue_data()
{
// regression test to check whether changes in KoUnit changes the conversion output
QTest::addColumn<KoUnit::Type>("type");
QTest::addColumn<qreal>("value");
QTest::addColumn<qreal>("expected");
QTest::addColumn<qreal>("expectedRounded");
// 1000.0
QTest::newRow("point 1000") << KoUnit::Point << 1000.0 << 1000.0 << 1000.0;
QTest::newRow("pica 1000") << KoUnit::Pica << 1000.0 << 83.3333330000 << 83.3333300000;
QTest::newRow("pixel 1000") << KoUnit::Pixel << 1000.0 << 1000.0 << 1000.0;
QTest::newRow("inch 1000") << KoUnit::Inch << 1000.0 << 13.8888888889 << 13.8888800000;
QTest::newRow("decimeter 1000") << KoUnit::Decimeter << 1000.0 << 3.5277716700 << 3.5277000000;
// 1.37
QTest::newRow("point 1.37") << KoUnit::Point << 1.37 << 1.37 << 1.37;
QTest::newRow("pica 1.37") << KoUnit::Pica << 1.37 << 0.114166666210 << 0.1141600000;
QTest::newRow("pixel 1.37") << KoUnit::Pixel << 1.37 << 1.37 << 1.37;
QTest::newRow("inch 1.37") << KoUnit::Inch << 1.37 << 0.019027777777779 << 0.019020000000;
QTest::newRow("decimeter 1.37") << KoUnit::Decimeter << 1.37 << 0.004833047187900 << 0.004800000000;
// 0.0001111
QTest::newRow("point 0.0001111") << KoUnit::Point << 0.0001111 << 0.000111100000 << 0.0 ;
QTest::newRow("pica 0.0001111") << KoUnit::Pica << 0.0001111 << 0.00000925833329630 << 0.0;
QTest::newRow("pixel 0.0001111") << KoUnit::Pixel << 0.0001111 << 0.000111100000 << 0.000111100000 ;
QTest::newRow("inch 0.0001111") << KoUnit::Inch << 0.0001111 << 0.00000154305555555568 << 0.0;
QTest::newRow("decimeter 0.0001111") << KoUnit::Decimeter << 0.0001111 << 0.00000039193543253700 << 0.0;
}
void TestKoUnit::testToUserValue()
{
QFETCH(KoUnit::Type, type);
QFETCH(qreal, value);
QFETCH(qreal, expected);
QFETCH(qreal, expectedRounded);
KoUnit unit = KoUnit(type);
qreal exphere = unit.toUserValue(value, false);
qreal expRound = unit.toUserValue(value, true);
QCOMPARE(exphere, expected);
QCOMPARE(expRound, expectedRounded);
}
QTEST_GUILESS_MAIN(TestKoUnit)
......@@ -40,6 +40,8 @@ private Q_SLOTS:
void testFromSymbol();
void testListForUi_data();
void testListForUi();
void testToUserValue_data();
void testToUserValue();
};
#endif
......@@ -212,7 +212,7 @@ void KisCustomImageWidget::widthUnitChanged(int index)
doubleWidth->setDecimals(2);
}
doubleWidth->setValue(KoUnit::ptToUnit(m_width, m_widthUnit));
doubleWidth->setValue(m_widthUnit.toUserValuePrecise(m_width));
doubleWidth->blockSignals(false);
changeDocumentInfoLabel();
......@@ -236,7 +236,7 @@ void KisCustomImageWidget::heightUnitChanged(int index)
doubleHeight->setDecimals(2);
}
doubleHeight->setValue(KoUnit::ptToUnit(m_height, m_heightUnit));
doubleHeight->setValue(m_heightUnit.toUserValuePrecise(m_height));
doubleHeight->blockSignals(false);
changeDocumentInfoLabel();
......@@ -297,8 +297,8 @@ KisDocument* KisCustomImageWidget::createNewImage()
double resolution;
resolution = doubleResolution->value() / 72.0; // internal resolution is in pixels per pt
width = static_cast<qint32>(0.5 + KoUnit::ptToUnit(m_width, KoUnit(KoUnit::Pixel, resolution)));
height = static_cast<qint32>(0.5 + KoUnit::ptToUnit(m_height, KoUnit(KoUnit::Pixel, resolution)));
width = static_cast<qint32>(0.5 + KoUnit(KoUnit::Pixel, resolution).toUserValuePrecise(m_width));
height = static_cast<qint32>(0.5 + KoUnit(KoUnit::Pixel, resolution).toUserValuePrecise(m_height));
QColor qc = cmbColor->color().toQColor();
qc.setAlpha(backgroundOpacity());
......@@ -499,8 +499,8 @@ void KisCustomImageWidget::changeDocumentInfoLabel()
double resolution;
resolution = doubleResolution->value() / 72.0; // internal resolution is in pixels per pt
width = static_cast<qint64>(0.5 + KoUnit::ptToUnit(m_width, KoUnit(KoUnit::Pixel, resolution)));
height = static_cast<qint64>(0.5 + KoUnit::ptToUnit(m_height, KoUnit(KoUnit::Pixel, resolution)));
width = static_cast<qint64>(0.5 + KoUnit(KoUnit::Pixel, resolution).toUserValuePrecise(m_width));
height = static_cast<qint64>(0.5 + KoUnit(KoUnit::Pixel, resolution).toUserValuePrecise(m_height));
qint64 layerSize = width * height;
const KoColorSpace *cs = colorSpaceSelector->currentColorSpace();
......
......@@ -114,7 +114,7 @@ QValidator::State KoUnitDoubleSpinBox::validate(QString &input, int &pos) const
warnWidgets << "Not a number: " << number;
return QValidator::Invalid;
}
newVal = KoUnit::ptToUnit( newVal, d->unit );
newVal = d->unit.toUserValuePrecise(newVal);
//input = textFromValue( newVal ); // don't overwrite for now; the effect is not exactly what I expect...
return QValidator::Acceptable;
......@@ -149,7 +149,7 @@ void KoUnitDoubleSpinBox::setUnit( const KoUnit &unit )
QDoubleSpinBox::setSingleStep( step );
d->unit = unit;
QDoubleSpinBox::setValue( KoUnit::ptToUnit( oldvalue, unit ) );
QDoubleSpinBox::setValue(unit.toUserValuePrecise(oldvalue));
setSuffix(unit.symbol().prepend(QLatin1Char(' ')));
}
......
......@@ -368,7 +368,7 @@ qreal KisSpinBoxUnitManager::getConversionFactor(int dim, QString symbol) const
if (! ok) {
break;
}
factor = unit.ptToUnit(1.0, unit); // use the precise function
factor = unit.toUserValuePrecise(1.0); // use the precise function
} while (0) ;
break;
......
......@@ -132,11 +132,11 @@ qreal EnhancedPathNamedParameter::evaluate()
break;
case IdentifierLogwidth:
// TODO: ? viewBox does not have any unit or const relation to mm
return KoUnit::toMillimeter(viewBox.width()) * 100;
return KoUnit(KoUnit::Millimeter).toUserValue(viewBox.width()) * 100;
break;
case IdentifierLogheight:
// TODO: ? viewBox does not have any unit or const relation to mm
return KoUnit::toMillimeter(viewBox.height()) * 100;
return KoUnit(KoUnit::Millimeter).toUserValue(viewBox.height()) * 100;
break;
default:
break;
......
......@@ -154,7 +154,7 @@ void ParagraphBulletsNumbers::setDisplay(KoParagraphStyle *style, int level)
case KoListStyle::ListTab:
widget.doubleSpinBox->setEnabled(true);
widget.labelFollowedBy->setCurrentIndex(0);
widget.doubleSpinBox->setValue(KoUnit::toCentimeter(llp.tabStopPosition()));
widget.doubleSpinBox->setValue(KoUnit(KoUnit::Centimeter).toUserValue(llp.tabStopPosition()));
break;
case KoListStyle::Space:
widget.doubleSpinBox->setEnabled(false);
......@@ -168,8 +168,8 @@ void ParagraphBulletsNumbers::setDisplay(KoParagraphStyle *style, int level)
Q_ASSERT(false);
}
widget.doubleSpinBox_2->setValue(KoUnit::toCentimeter(llp.margin()));
widget.doubleSpinBox_3->setValue(KoUnit::toCentimeter(llp.margin()) + KoUnit::toCentimeter(llp.textIndent()));
widget.doubleSpinBox_2->setValue(KoUnit(KoUnit::Centimeter).toUserValue(llp.margin()));
widget.doubleSpinBox_3->setValue(KoUnit(KoUnit::Centimeter).toUserValue(llp.margin()) + KoUnit(KoUnit::Centimeter).toUserValue(llp.textIndent()));
}
// *** features not in GUI;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment