File indexing completed on 2024-05-12 04:33:58

0001 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
0002 // pageSize.cpp
0003 //
0004 // Part of KVIEWSHELL - A framework for multipage text/gfx viewers
0005 //
0006 // SPDX-FileCopyrightText: 2002-2003 Stefan Kebekus
0007 // SPDX-License-Identifier: GPL-2.0-or-later
0008 
0009 #include <config.h>
0010 
0011 #include "debug_dvi.h"
0012 #include "length.h"
0013 #include "pageSize.h"
0014 
0015 #include <KLocalizedString>
0016 
0017 #include <QLocale>
0018 #include <QLoggingCategory>
0019 
0020 struct pageSizeItem {
0021     const char *name;
0022     float width;  // in mm
0023     float height; // in mm
0024     const char *preferredUnit;
0025 };
0026 
0027 #define defaultMetricPaperSize 4   // Default paper size is "DIN A4"
0028 #define defaultImperialPaperSize 8 // Default paper size is "US Letter"
0029 
0030 static const pageSizeItem staticList[] = {
0031     {"DIN A0", 841.0f, 1189.0f, "mm"},
0032     {"DIN A1", 594.0f, 841.0f, "mm"},
0033     {"DIN A2", 420.0f, 594.0f, "mm"},
0034     {"DIN A3", 297.0f, 420.0f, "mm"},
0035     {"DIN A4", 210.0f, 297.0f, "mm"},
0036     {"DIN A5", 148.5f, 210.0f, "mm"},
0037     {"DIN B4", 250.0f, 353.0f, "mm"},
0038     {"DIN B5", 176.0f, 250.0f, "mm"},
0039     {"US Letter", 215.9f, 279.4f, "in"},
0040     {"US Legal", 215.9f, 355.6f, "in"},
0041     {nullptr, 0.0f, 0.0f, nullptr} // marks the end of the list.
0042 };
0043 
0044 pageSize::pageSize()
0045 {
0046     currentSize = defaultPageSize();
0047     pageWidth.setLength_in_mm(staticList[currentSize].width);
0048     pageHeight.setLength_in_mm(staticList[currentSize].height);
0049 }
0050 
0051 pageSize::pageSize(const SimplePageSize &s)
0052 {
0053     pageWidth = s.width();
0054     pageHeight = s.height();
0055 
0056     rectifySizes();
0057     reconstructCurrentSize();
0058 }
0059 
0060 bool pageSize::setPageSize(const QString &name)
0061 {
0062     // See if we can recognize the string
0063     QString currentName;
0064     for (int i = 0; staticList[i].name != nullptr; i++) {
0065         currentName = QString::fromLocal8Bit(staticList[i].name);
0066         if (currentName == name) {
0067             currentSize = i;
0068             // Set page width/height accordingly
0069             pageWidth.setLength_in_mm(staticList[currentSize].width);
0070             pageHeight.setLength_in_mm(staticList[currentSize].height);
0071             Q_EMIT sizeChanged(*this);
0072             return true;
0073         }
0074     }
0075 
0076     // Check if the string contains 'x'. If yes, we assume it is of type
0077     // "<number>x<number>". If yes, the first number is interpreted as
0078     // the width in mm, the second as the height in mm
0079     if (name.indexOf(QLatin1Char('x')) >= 0) {
0080         bool wok, hok;
0081         float pageWidth_tmp = name.section(QLatin1Char('x'), 0, 0).toFloat(&wok);
0082         float pageHeight_tmp = name.section(QLatin1Char('x'), 1, 1).toFloat(&hok);
0083         if (wok && hok) {
0084             pageWidth.setLength_in_mm(pageWidth_tmp);
0085             pageHeight.setLength_in_mm(pageHeight_tmp);
0086 
0087             rectifySizes();
0088             reconstructCurrentSize();
0089             Q_EMIT sizeChanged(*this);
0090             return true;
0091         }
0092     }
0093 
0094     // Check if the string contains ','. If yes, we assume it is of type
0095     // "<number><unit>,<number><uni>". The first number is supposed to
0096     // be the width, the second the height.
0097     if (name.indexOf(QLatin1Char(',')) >= 0) {
0098         bool wok, hok;
0099         float pageWidth_tmp = Length::convertToMM(name.section(QLatin1Char(','), 0, 0), &wok);
0100         float pageHeight_tmp = Length::convertToMM(name.section(QLatin1Char(','), 1, 1), &hok);
0101         if (wok && hok) {
0102             pageWidth.setLength_in_mm(pageWidth_tmp);
0103             pageHeight.setLength_in_mm(pageHeight_tmp);
0104 
0105             rectifySizes();
0106             reconstructCurrentSize();
0107             Q_EMIT sizeChanged(*this);
0108             return true;
0109         }
0110     }
0111 
0112     // Last resource. Set the default, in case the string is
0113     // unintelligible to us.
0114     currentSize = defaultPageSize();
0115     pageWidth.setLength_in_mm(staticList[currentSize].width);
0116     pageHeight.setLength_in_mm(staticList[currentSize].height);
0117     qCCritical(OkularDviShellDebug) << "pageSize::setPageSize: could not parse '" << name << "'. Using " << staticList[currentSize].name << " as a default.";
0118     Q_EMIT sizeChanged(*this);
0119     return false;
0120 }
0121 
0122 void pageSize::setPageSize(double width, double height)
0123 {
0124     SimplePageSize oldPage = *this;
0125 
0126     pageWidth.setLength_in_mm(width);
0127     pageHeight.setLength_in_mm(height);
0128 
0129     rectifySizes();
0130     reconstructCurrentSize();
0131     if (!isNearlyEqual(oldPage)) {
0132         Q_EMIT sizeChanged(*this);
0133     }
0134 }
0135 
0136 void pageSize::setPageSize(const QString &width, const QString &_widthUnits, const QString &height, const QString &_heightUnits)
0137 {
0138     SimplePageSize oldPage = *this;
0139 
0140     double w = width.toFloat();
0141     double h = height.toFloat();
0142 
0143     QString widthUnits = _widthUnits;
0144     if ((widthUnits != QLatin1String("cm")) && (widthUnits != QLatin1String("mm")) && (widthUnits != QLatin1String("in"))) {
0145         qCCritical(OkularDviShellDebug) << "Unrecognized page width unit '" << widthUnits << "'. Assuming mm";
0146         widthUnits = QStringLiteral("mm");
0147     }
0148     pageWidth.setLength_in_mm(w);
0149     if (widthUnits == QLatin1String("cm")) {
0150         pageWidth.setLength_in_cm(w);
0151     }
0152     if (widthUnits == QLatin1String("in")) {
0153         pageWidth.setLength_in_inch(w);
0154     }
0155 
0156     QString heightUnits = _heightUnits;
0157     if ((heightUnits != QLatin1String("cm")) && (heightUnits != QLatin1String("mm")) && (heightUnits != QLatin1String("in"))) {
0158         qCCritical(OkularDviShellDebug) << "Unrecognized page height unit '" << widthUnits << "'. Assuming mm";
0159         heightUnits = QStringLiteral("mm");
0160     }
0161     pageHeight.setLength_in_mm(h);
0162     if (heightUnits == QLatin1String("cm")) {
0163         pageHeight.setLength_in_cm(h);
0164     }
0165     if (heightUnits == QLatin1String("in")) {
0166         pageHeight.setLength_in_inch(h);
0167     }
0168 
0169     rectifySizes();
0170     reconstructCurrentSize();
0171     if (!isNearlyEqual(oldPage)) {
0172         Q_EMIT sizeChanged(*this);
0173     }
0174 }
0175 
0176 void pageSize::rectifySizes()
0177 {
0178     // Now do some sanity checks to make sure that values are not
0179     // outrageous. We allow values between 5cm and 50cm.
0180     if (pageWidth.getLength_in_mm() < 50) {
0181         pageWidth.setLength_in_mm(50.0);
0182     }
0183     if (pageWidth.getLength_in_mm() > 1200) {
0184         pageWidth.setLength_in_mm(1200);
0185     }
0186     if (pageHeight.getLength_in_mm() < 50) {
0187         pageHeight.setLength_in_mm(50);
0188     }
0189     if (pageHeight.getLength_in_mm() > 1200) {
0190         pageHeight.setLength_in_mm(1200);
0191     }
0192     return;
0193 }
0194 
0195 QString pageSize::preferredUnit() const
0196 {
0197     if (currentSize >= 0) {
0198         return QString::fromLocal8Bit(staticList[currentSize].preferredUnit);
0199     }
0200 
0201     // User-defined size. Give a preferred unit depending on the locale.
0202     if (QLocale::system().measurementSystem() == QLocale::MetricSystem) {
0203         return QStringLiteral("mm");
0204     } else {
0205         return QStringLiteral("in");
0206     }
0207 }
0208 
0209 QString pageSize::widthString(const QString &unit) const
0210 {
0211     QString answer = QStringLiteral("--");
0212 
0213     if (unit == QLatin1String("cm")) {
0214         answer.setNum(pageWidth.getLength_in_cm());
0215     }
0216     if (unit == QLatin1String("mm")) {
0217         answer.setNum(pageWidth.getLength_in_mm());
0218     }
0219     if (unit == QLatin1String("in")) {
0220         answer.setNum(pageWidth.getLength_in_inch());
0221     }
0222 
0223     return answer;
0224 }
0225 
0226 QString pageSize::heightString(const QString &unit) const
0227 {
0228     QString answer = QStringLiteral("--");
0229 
0230     if (unit == QLatin1String("cm")) {
0231         answer.setNum(pageHeight.getLength_in_cm());
0232     }
0233     if (unit == QLatin1String("mm")) {
0234         answer.setNum(pageHeight.getLength_in_mm());
0235     }
0236     if (unit == QLatin1String("in")) {
0237         answer.setNum(pageHeight.getLength_in_inch());
0238     }
0239 
0240     return answer;
0241 }
0242 
0243 QStringList pageSize::pageSizeNames()
0244 {
0245     QStringList names;
0246 
0247     for (int i = 0; staticList[i].name != nullptr; i++) {
0248         names << QString::fromLocal8Bit(staticList[i].name);
0249     }
0250 
0251     return names;
0252 }
0253 
0254 QString pageSize::formatName() const
0255 {
0256     if (currentSize >= 0) {
0257         return QString::fromLocal8Bit(staticList[currentSize].name);
0258     } else {
0259         return QString();
0260     }
0261 }
0262 
0263 int pageSize::getOrientation() const
0264 {
0265     if (currentSize == -1) {
0266         qCCritical(OkularDviShellDebug) << "pageSize::getOrientation: getOrientation called for page format that does not have a name.";
0267         return 0;
0268     }
0269 
0270     if (pageWidth.getLength_in_mm() == staticList[currentSize].width) {
0271         return 0;
0272     } else {
0273         return 1;
0274     }
0275 }
0276 
0277 void pageSize::setOrientation(int orient)
0278 {
0279     if (currentSize == -1) {
0280         qCCritical(OkularDviShellDebug) << "pageSize::setOrientation: setOrientation called for page format that does not have a name.";
0281         return;
0282     }
0283 
0284     if (orient == 1) {
0285         pageWidth.setLength_in_mm(staticList[currentSize].height);
0286         pageHeight.setLength_in_mm(staticList[currentSize].width);
0287     } else {
0288         pageWidth.setLength_in_mm(staticList[currentSize].width);
0289         pageHeight.setLength_in_mm(staticList[currentSize].height);
0290     }
0291     Q_EMIT sizeChanged(*this);
0292 }
0293 
0294 QString pageSize::serialize() const
0295 {
0296     if ((currentSize >= 0) && (fabs(staticList[currentSize].height - pageHeight.getLength_in_mm()) <= 0.5)) {
0297         return QString::fromLocal8Bit(staticList[currentSize].name);
0298     } else {
0299         return QStringLiteral("%1x%2").arg(pageWidth.getLength_in_mm()).arg(pageHeight.getLength_in_mm());
0300     }
0301 }
0302 
0303 QString pageSize::description() const
0304 {
0305     if (!isValid()) {
0306         return QString();
0307     }
0308 
0309     QString size = QStringLiteral(" ");
0310     if (formatNumber() == -1) {
0311         if (QLocale::system().measurementSystem() == QLocale::MetricSystem) {
0312             size += QStringLiteral("%1x%2 mm").arg(width().getLength_in_mm(), 0, 'f', 0).arg(height().getLength_in_mm(), 0, 'f', 0);
0313         } else {
0314             size += QStringLiteral("%1x%2 in").arg(width().getLength_in_inch(), 0, 'g', 2).arg(height().getLength_in_inch(), 0, 'g', 2);
0315         }
0316     } else {
0317         size += formatName() + QLatin1Char('/');
0318         if (getOrientation() == 0) {
0319             size += i18n("portrait");
0320         } else {
0321             size += i18n("landscape");
0322         }
0323     }
0324     return size + QLatin1Char(' ');
0325 }
0326 
0327 void pageSize::reconstructCurrentSize()
0328 {
0329     for (int i = 0; staticList[i].name != nullptr; i++) {
0330         if ((fabs(staticList[i].width - pageWidth.getLength_in_mm()) <= 2) && (fabs(staticList[i].height - pageHeight.getLength_in_mm()) <= 2)) {
0331             currentSize = i;
0332             pageWidth.setLength_in_mm(staticList[currentSize].width);
0333             pageHeight.setLength_in_mm(staticList[currentSize].height);
0334             return;
0335         }
0336         if ((fabs(staticList[i].height - pageWidth.getLength_in_mm()) <= 2) && (fabs(staticList[i].width - pageHeight.getLength_in_mm()) <= 2)) {
0337             currentSize = i;
0338             pageWidth.setLength_in_mm(staticList[currentSize].height);
0339             pageHeight.setLength_in_mm(staticList[currentSize].width);
0340             return;
0341         }
0342     }
0343     currentSize = -1;
0344     return;
0345 }
0346 
0347 int pageSize::defaultPageSize()
0348 {
0349     // FIXME: static_cast<QPrinter::PageSize>(KLocale::global()->pageSize())
0350     //        is the proper solution here.  Then you can determine the values
0351     //        without using your hardcoded table too!
0352     if (QLocale::system().measurementSystem() == QLocale::MetricSystem) {
0353         return defaultMetricPaperSize;
0354     } else {
0355         return defaultImperialPaperSize;
0356     }
0357 }