Merge remote-tracking branch 'upstream/master' into experiment/upstream-sync

Change-Id: I77c2bb8abdef222cf0fc2f7016e34da1554653cb
This commit is contained in:
2026-09-28 18:32:53 +02:00
614 changed files with 15248 additions and 6442 deletions
-1
View File
@@ -206,7 +206,6 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S
$(call fetch_Optional,MORE_FONTS,FONT_ALEF_TARBALL) \
$(call fetch_Optional,MORE_FONTS,FONT_AMIRI_TARBALL) \
$(call fetch_Optional,MORE_FONTS,FONT_REEM_TARBALL) \
$(call fetch_Optional,MORE_FONTS,FONT_SCHEHERAZADE_TARBALL) \
$(call fetch_Optional,MESON,MESON_TARBALL) \
$(call fetch_Optional,MSPUB,MSPUB_TARBALL) \
$(call fetch_Optional,MWAW,MWAW_TARBALL) \
-1
View File
@@ -1080,7 +1080,6 @@ $(eval $(call gb_Helper_register_packages_for_install,ooo_fonts,\
fonts_noto_serif_hebrew \
fonts_noto_serif_lao \
fonts_reem \
fonts_scheherazade \
) \
))
+2 -2
View File
@@ -1388,7 +1388,7 @@ endif
define gb_LinkTarget__use_cairo
$(call gb_LinkTarget_use_package,$(1),cairo)
$(call gb_LinkTarget_use_package,$(1),pixman)
$(call gb_LinkTarget_use_external,$(1),freetype_headers)
$(call gb_LinkTarget_use_external,$(1),freetype)
$(call gb_LinkTarget_set_include,$(1),\
-I$(gb_UnpackedTarball_workdir)/cairo \
-I$(gb_UnpackedTarball_workdir)/cairo/src \
@@ -4251,7 +4251,7 @@ gb_ExternalExecutable__register_xmllint :=
else # ! SYSTEM_LIBXML_FOR_BUILD
define gb_ExternalExecutable__register_xmllint
$(call gb_ExternalExecutable_set_internal,xmllint,$(WORKDIR_FOR_BUILD)/UnpackedTarball/libxml2/$(if $(filter MSC,$(COM)),$(if $(MSVC_USE_DEBUG_RUNTIME),Debug,Release))/xmllint$(gb_Executable_EXT_for_build),libxml2)
$(call gb_ExternalExecutable_set_internal,xmllint,$(WORKDIR_FOR_BUILD)/UnpackedTarball/libxml2/xmllint$(gb_Executable_EXT_for_build),libxml2)
$(call gb_ExternalExecutable_add_dependencies,xmllint,\
$(if $(filter WNT,$(OS)),$(call gb_Package_get_target,icu_ure)) \
$(call gb_Package_get_target,libxml2) \
+1
View File
@@ -74,6 +74,7 @@
<!-- OTHER -->
<data android:mimeType="text/csv"/>
<data android:mimeType="text/comma-separated-values"/>
<data android:mimeType="text/markdown"/>
<data android:mimeType="application/vnd.ms-works" />
<data android:mimeType="application/vnd.apple.keynote" />
<data android:mimeType="application/x-abiword" />
+2 -2
View File
@@ -86,7 +86,7 @@
<string name="alert_ok">OK</string>
<string name="alert_cancel">Annuleren</string>
<string name="current_uno_command">Huidige UNO-opdracht</string>
<string name="pdf_export_finished">PDF-export voltooit</string>
<string name="pdf_export_finished">PDF-export voltooid</string>
<string name="unable_to_export_pdf">Kan niet exporteren naar PDF</string>
<string name="unable_to_save">Kan bestand niet opslaan</string>
<string name="error">Fout</string>
@@ -106,7 +106,7 @@
<string name="pref_experimental_editing">Experimentele modus</string>
<string name="pref_developer_mode_summary">Schakel de ontwikkelaarsmodus in, waarin u UNO-opdrachten binnen de app kunt verzenden. Gebruik op eigen risico.</string>
<string name="action_save_as">Opslaan als…</string>
<string name="message_saved">Opslaan voltooit</string>
<string name="message_saved">Opslaan voltooid</string>
<string name="save_alert_dialog_title">Het document opslaan voordat u het sluit?</string>
<string name="calc_optimal_length_default_text">Extra lengte invoeren in 100ste/mm</string>
<string name="compress_photo_max_quality">Maximale kwaliteit</string>
@@ -330,11 +330,16 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Shared
private boolean copyFileToTemp(Uri documentUri) {
// CSV files need a .csv suffix to be opened in Calc.
// Markdown files need an .md suffix to be imported as Markdown and not plain text
String suffix = null;
String intentType = getIntent().getType();
if (intentType == null)
intentType = getContentResolver().getType(documentUri);
// K-9 mail uses the first, GMail uses the second variant.
if ("text/comma-separated-values".equals(intentType) || "text/csv".equals(intentType))
suffix = ".csv";
else if ("text/markdown".equals(intentType))
suffix = ".md";
try {
mTempFile = File.createTempFile("LibreOffice", suffix, this.getCacheDir());
@@ -85,6 +85,7 @@ public class FileUtilities {
// Other
mExtnMap.put(".csv", CALC);
mExtnMap.put(".md", DOC);
mExtnMap.put(".wps", DOC);
mExtnMap.put(".key", IMPRESS);
mExtnMap.put(".abw", DOC);
@@ -111,6 +111,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements View.OnC
"application/vnd.openxmlformats-officedocument.presentationml.template",
"text/csv",
"text/comma-separated-values",
"text/markdown",
"application/vnd.ms-works",
"application/vnd.apple.keynote",
"application/x-abiword",
+1 -1
View File
@@ -1,6 +1,6 @@
[versions]
constraintlayout_version = "2.2.1"
gradle_version = "9.3.1"
gradle_version = "9.4.1"
material_version = "1.13.0"
preference_version = "1.2.1"
+2 -2
View File
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=a3c4ba4aca8f0075688b9c5b18939fd28e8cb4357c227da5c1d9f38343791439
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-all.zip
distributionSha256Sum=87a2216cc1f9122192d4e0fe905ffdf1b4c72cff797e9f733b174e157cadd396
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-all.zip
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+2 -2
View File
@@ -22,8 +22,8 @@
#include "ddectrl.hxx"
#include <basic/sberrors.hxx>
#define DDE_FIRSTERR 0x4000
#define DDE_LASTERR 0x4011
constexpr tools::Long DDE_FIRSTERR = 0x4000;
constexpr tools::Long DDE_LASTERR = 0x4011;
const ErrCode nDdeErrMap[] =
{
+2
View File
@@ -185,6 +185,8 @@
#define STR_INVALID_TIME_UNIT NC_("STR_INVALID_TIME_UNIT", "The major and minor interval need to be greater or equal to the resolution. Check your input.")
#define STR_UNSUPPORTED_CHART_TYPE NC_("STR_UNSUPPORTED_CHART_TYPE", "One or more chart types are unsupported in this version of %PRODUCTNAME")
#define STR_RANGE_FOR_VALUETYPE NC_("STR_RANGE_FOR_VALUETYPE", "Ran~ge for %VALUETYPE")
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+63
View File
@@ -14,6 +14,9 @@
#include <com/sun/star/chart2/RelativePosition.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/chart/XChartDocument.hpp>
#include <com/sun/star/chart/XDiagram.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/chart2/PieChartSubType.hpp>
#include <com/sun/star/chart2/XInternalDataProvider.hpp>
#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
#include <com/sun/star/chart/XAxisXSupplier.hpp>
@@ -2038,6 +2041,66 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, TestParetoDefaultColor)
CPPUNIT_ASSERT_EQUAL(nCorrectColor, nFillColor);
}
CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf164516BarOfPieDiagram)
{
loadFromFile(u"ods/chart.ods");
uno::Reference<lang::XComponent> xChartComp = getChartCompFromSheet(0, 0);
uno::Reference<chart::XChartDocument> xChartDoc(xChartComp, uno::UNO_QUERY_THROW);
uno::Reference<lang::XMultiServiceFactory> xFactory(xChartDoc, uno::UNO_QUERY_THROW);
// tdf#164516 - switch the chart type to bar-of-pie using the chart API
uno::Reference<chart::XDiagram> xDiagram(
xFactory->createInstance(u"com.sun.star.chart.BarOfPieDiagram"_ustr), uno::UNO_QUERY);
xChartDoc->setDiagram(xDiagram);
// Without the fix in place, this test would have failed with
// - Expected: com.sun.star.chart.BarOfPieDiagram
// - Actual : com.sun.star.chart.BarDiagram
// i.e. the service name was unknown and the chart stays a bar chart
CPPUNIT_ASSERT_EQUAL(u"com.sun.star.chart.BarOfPieDiagram"_ustr,
xChartDoc->getDiagram()->getDiagramType());
uno::Reference<chart2::XChartDocument> xChart2Doc(xChartComp, uno::UNO_QUERY_THROW);
uno::Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChart2Doc, 0);
CPPUNIT_ASSERT_EQUAL(u"com.sun.star.chart2.PieChartType"_ustr, xChartType->getChartType());
uno::Reference<beans::XPropertySet> xPropSet(xChartType, uno::UNO_QUERY_THROW);
chart2::PieChartSubType eSubType;
CPPUNIT_ASSERT(xPropSet->getPropertyValue(u"SubPieType"_ustr) >>= eSubType);
CPPUNIT_ASSERT_EQUAL(chart2::PieChartSubType_BAR, eSubType);
}
CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf164516PieOfPieDiagram)
{
loadFromFile(u"ods/chart.ods");
uno::Reference<lang::XComponent> xChartComp = getChartCompFromSheet(0, 0);
uno::Reference<chart::XChartDocument> xChartDoc(xChartComp, uno::UNO_QUERY_THROW);
uno::Reference<lang::XMultiServiceFactory> xFactory(xChartDoc, uno::UNO_QUERY_THROW);
// tdf#164516 - switch the chart type to pie-of-pie using the chart API
uno::Reference<chart::XDiagram> xDiagram(
xFactory->createInstance(u"com.sun.star.chart.PieOfPieDiagram"_ustr), uno::UNO_QUERY);
xChartDoc->setDiagram(xDiagram);
// Without the fix in place, this test would have failed with
// - Expected: com.sun.star.chart.PieOfPieDiagram
// - Actual : com.sun.star.chart.BarDiagram
// i.e. the service name was unknown and the chart stays a bar chart
CPPUNIT_ASSERT_EQUAL(u"com.sun.star.chart.PieOfPieDiagram"_ustr,
xChartDoc->getDiagram()->getDiagramType());
uno::Reference<chart2::XChartDocument> xChart2Doc(xChartComp, uno::UNO_QUERY_THROW);
uno::Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChart2Doc, 0);
CPPUNIT_ASSERT_EQUAL(u"com.sun.star.chart2.PieChartType"_ustr, xChartType->getChartType());
uno::Reference<beans::XPropertySet> xPropSet(xChartType, uno::UNO_QUERY_THROW);
chart2::PieChartSubType eSubType;
CPPUNIT_ASSERT(xPropSet->getPropertyValue(u"SubPieType"_ustr) >>= eSubType);
CPPUNIT_ASSERT_EQUAL(chart2::PieChartSubType_PIE, eSubType);
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -84,6 +84,8 @@ enum eServiceType
SERVICE_NAME_NET_DIAGRAM,
SERVICE_NAME_FILLED_NET_DIAGRAM,
SERVICE_NAME_PIE_DIAGRAM,
SERVICE_NAME_BAR_OF_PIE_DIAGRAM,
SERVICE_NAME_PIE_OF_PIE_DIAGRAM,
SERVICE_NAME_STOCK_DIAGRAM,
SERVICE_NAME_XY_DIAGRAM,
SERVICE_NAME_BUBBLE_DIAGRAM,
@@ -114,6 +116,8 @@ tServiceNameMap & lcl_getStaticServiceNameMap()
{"com.sun.star.chart.NetDiagram", SERVICE_NAME_NET_DIAGRAM},
{"com.sun.star.chart.FilledNetDiagram", SERVICE_NAME_FILLED_NET_DIAGRAM},
{"com.sun.star.chart.PieDiagram", SERVICE_NAME_PIE_DIAGRAM},
{"com.sun.star.chart.BarOfPieDiagram", SERVICE_NAME_BAR_OF_PIE_DIAGRAM},
{"com.sun.star.chart.PieOfPieDiagram", SERVICE_NAME_PIE_OF_PIE_DIAGRAM},
{"com.sun.star.chart.StockDiagram", SERVICE_NAME_STOCK_DIAGRAM},
{"com.sun.star.chart.XYDiagram", SERVICE_NAME_XY_DIAGRAM},
{"com.sun.star.chart.BubbleDiagram", SERVICE_NAME_BUBBLE_DIAGRAM},
@@ -1207,6 +1211,22 @@ uno::Reference< uno::XInterface > SAL_CALL ChartDocumentWrapper::createInstance(
bCreateDiagram = true;
}
break;
case SERVICE_NAME_BAR_OF_PIE_DIAGRAM:
if (xChartTypeManager.is())
{
xTemplate = xChartTypeManager->createTemplate(
u"com.sun.star.chart2.template.BarOfPie"_ustr);
bCreateDiagram = true;
}
break;
case SERVICE_NAME_PIE_OF_PIE_DIAGRAM:
if (xChartTypeManager.is())
{
xTemplate = xChartTypeManager->createTemplate(
u"com.sun.star.chart2.template.PieOfPie"_ustr);
bCreateDiagram = true;
}
break;
case SERVICE_NAME_STOCK_DIAGRAM:
if( xChartTypeManager.is())
{
@@ -183,7 +183,6 @@ DataSourceTabPage::DataSourceTabPage(weld::Container* pPage, weld::DialogControl
m_xLB_ROLE->get_height_rows(5));
m_xFT_CAPTION->set_visible(!bHideDescription);
m_aFixedTextRange = m_xFT_RANGE->get_label();
SetPageTitle(SchResId(STR_OBJECT_DATASERIES_PLURAL));
// set handlers
@@ -473,15 +472,9 @@ IMPL_LINK_NOARG(DataSourceTabPage, RoleSelectionChangedHdl, weld::ItemView&, voi
OUString aSelectedRoleUI = lcl_GetSelectedRole( *m_xLB_ROLE, true );
OUString aSelectedRange = lcl_GetSelectedRolesRange( *m_xLB_ROLE );
// replace role in fixed text label
static constexpr OUString aReplacementStr( u"%VALUETYPE"_ustr );
sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr );
if( nIndex != -1 )
{
// add the role in fixed text label
m_xFT_RANGE->set_label(
m_aFixedTextRange.replaceAt(
nIndex, aReplacementStr.getLength(), aSelectedRoleUI ));
}
SchResId(STR_RANGE_FOR_VALUETYPE).replaceFirst(u"%VALUETYPE", aSelectedRoleUI));
m_xEDT_RANGE->set_text(aSelectedRange);
isValid();
@@ -121,8 +121,6 @@ private:
std::vector<std::unique_ptr<SeriesEntry>> m_aEntries;
OUString m_aFixedTextRange;
ChartTypeTemplateProvider * m_pTemplateProvider;
DialogModel & m_rDialogModel;
weld::Entry* m_pCurrentRangeChoosingField;
@@ -13,12 +13,19 @@
#include <DataSeries.hxx>
#include <DataSeriesHelper.hxx>
#include <PropertyHelper.hxx>
#include <Axis.hxx>
#include <AxisHelper.hxx>
#include <AxisIndexDefines.hxx>
#include <BaseCoordinateSystem.hxx>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/chart2/AxisType.hpp>
#include <comphelper/diagnose_ex.hxx>
#include <comphelper/property.hxx>
#include <algorithm>
using namespace ::com::sun::star;
@@ -188,6 +195,42 @@ void FunnelChartTypeTemplate::resetStyles2(const rtl::Reference<::chart::Diagram
xDiagram->setVertical(false);
}
bool FunnelChartTypeTemplate::isSwapXAndY() const
{
// Ordinate axis is vertical
return true;
}
void FunnelChartTypeTemplate::createCoordinateSystems(
const rtl::Reference<::chart::Diagram>& xDiagram)
{
ChartTypeTemplate::createCoordinateSystems(xDiagram);
xDiagram->setVertical(isSwapXAndY());
}
void FunnelChartTypeTemplate::adaptAxes(
const std::vector<rtl::Reference<BaseCoordinateSystem>>& rCoordSys)
{
// override to hide the horizontal (value) axis
ChartTypeTemplate::adaptAxes(rCoordSys);
if (rCoordSys.empty())
return;
for (rtl::Reference<BaseCoordinateSystem> const& xCooSys : rCoordSys)
{
if (!xCooSys.is())
continue;
rtl::Reference<Axis> xAxis = AxisHelper::getAxis(1, 0, xCooSys);
if (!xAxis.is())
continue;
xAxis->setPropertyValue(u"Show"_ustr, uno::Any(false));
}
}
IMPLEMENT_FORWARD_XINTERFACE2(FunnelChartTypeTemplate, ChartTypeTemplate, OPropertySet)
IMPLEMENT_FORWARD_XTYPEPROVIDER2(FunnelChartTypeTemplate, ChartTypeTemplate, OPropertySet)
@@ -45,12 +45,16 @@ protected:
::sal_Int32 nChartTypeGroupIndex, ::sal_Int32 nSeriesIndex,
::sal_Int32 nSeriesCount) override;
virtual void resetStyles2(const rtl::Reference<::chart::Diagram>& xDiagram) override;
virtual void createCoordinateSystems(const rtl::Reference<::chart::Diagram>& xDiagram) override;
// ____ ChartTypeTemplate ____
virtual sal_Int32 getDimension() const override;
virtual rtl::Reference<::chart::ChartType>
getChartTypeForIndex(sal_Int32 nChartTypeIndex) override;
virtual bool isSwapXAndY() const override;
virtual void
adaptAxes(const std::vector<rtl::Reference<BaseCoordinateSystem>>& rCoordSys) override;
private:
sal_Int32 m_nDim;
+73 -57
View File
@@ -38,6 +38,75 @@ typedef std::pair< double, double > tPointType;
typedef std::vector< tPointType > tPointVecType;
typedef tPointVecType::size_type lcl_tSizeType;
bool lcl_CalculateUpperTriangularForm(
tPointVecType& rPointsIn
, std::vector<std::vector<double>>& rMatN
, std::vector<lcl_tSizeType>& rShift )
{
lcl_tSizeType r = 0; // true row index
lcl_tSizeType c = 0; // true column index
double fDivisor = 1.0; // used for diagonal element
double fEliminate = 1.0; // used for the element, that will become zero
bool bIsSuccessful = true;
const lcl_tSizeType n = rPointsIn.size() - 1;
for (c = 0 ; c <= n && bIsSuccessful; ++c)
{
// search for first non-zero downwards
r = c;
while ( r < n && rMatN[r][c-rShift[r]] == 0 )
{
++r;
}
if (rMatN[r][c-rShift[r]] == 0.0)
{
// Matrix N is singular, although this is mathematically impossible
bIsSuccessful = false;
}
else
{
// exchange total row r with total row c if necessary
if (r != c)
{
std::swap( rMatN[r], rMatN[c] );
std::swap( rPointsIn[r], rPointsIn[c] );
std::swap( rShift[r], rShift[c] );
}
sal_uInt32 p = rMatN[c].size() - 1;
// divide row c, so that element(c,c) becomes 1
fDivisor = rMatN[c][c-rShift[c]]; // not zero, see above
for (sal_uInt32 i = 0; i <= p; ++i)
{
rMatN[c][i] /= fDivisor;
}
rPointsIn[c].first /= fDivisor;
rPointsIn[c].second /= fDivisor;
// eliminate forward, examine row c+1 to n-1 (worst case)
// stop if first non-zero element in row has an higher column as c
// look at nShift for that, elements in nShift are equal or increasing
for ( r = c+1; r < n && rShift[r]<=c ; ++r)
{
fEliminate = rMatN[r][0];
if (fEliminate != 0.0) // else accidentally zero, nothing to do
{
for (sal_uInt32 i = 1; i <= p; ++i)
{
rMatN[r][i-1] = rMatN[r][i] - fEliminate * rMatN[c][i];
}
rMatN[r][p]=0;
rPointsIn[r].first -= fEliminate * rPointsIn[c].first;
rPointsIn[r].second -= fEliminate * rPointsIn[c].second;
++rShift[r];
}
}
}
}
return bIsSuccessful;
}
class lcl_SplineCalculation
{
public:
@@ -719,63 +788,9 @@ void SplineCalculator::CalculateBSplines(
// Get matrix C of control points from the matrix equation aMatN * C = aPointsIn
// aPointsIn is overwritten with C.
// Gaussian elimination is possible without pivoting, see reference
lcl_tSizeType r = 0; // true row index
lcl_tSizeType c = 0; // true column index
double fDivisor = 1.0; // used for diagonal element
double fEliminate = 1.0; // used for the element, that will become zero
bool bIsSuccessful = true;
for (c = 0 ; c <= n && bIsSuccessful; ++c)
{
// search for first non-zero downwards
r = c;
while ( r < n && aMatN[r][c-aShift[r]] == 0 )
{
++r;
}
if (aMatN[r][c-aShift[r]] == 0.0)
{
// Matrix N is singular, although this is mathematically impossible
bIsSuccessful = false;
}
else
{
// exchange total row r with total row c if necessary
if (r != c)
{
std::swap( aMatN[r], aMatN[c] );
std::swap( aPointsIn[r], aPointsIn[c] );
std::swap( aShift[r], aShift[c] );
}
// divide row c, so that element(c,c) becomes 1
fDivisor = aMatN[c][c-aShift[c]]; // not zero, see above
for (sal_uInt32 i = 0; i <= p; ++i)
{
aMatN[c][i] /= fDivisor;
}
aPointsIn[c].first /= fDivisor;
aPointsIn[c].second /= fDivisor;
bool bIsSuccessful = lcl_CalculateUpperTriangularForm(aPointsIn, aMatN, aShift);
// eliminate forward, examine row c+1 to n-1 (worst case)
// stop if first non-zero element in row has an higher column as c
// look at nShift for that, elements in nShift are equal or increasing
for ( r = c+1; r < n && aShift[r]<=c ; ++r)
{
fEliminate = aMatN[r][0];
if (fEliminate != 0.0) // else accidentally zero, nothing to do
{
for (sal_uInt32 i = 1; i <= p; ++i)
{
aMatN[r][i-1] = aMatN[r][i] - fEliminate * aMatN[c][i];
}
aMatN[r][p]=0;
aPointsIn[r].first -= fEliminate * aPointsIn[c].first;
aPointsIn[r].second -= fEliminate * aPointsIn[c].second;
++aShift[r];
}
}
}
}// upper triangle form is reached
if( bIsSuccessful)
{
// eliminate backwards, begin with last column
@@ -785,10 +800,11 @@ void SplineCalculator::CalculateBSplines(
// diagonal are zero and do not influence other rows.
// Full matrix N has semibandwidth < p, therefore element(r,c) is
// zero, if abs(r-cc)>=p. abs(r-cc)=cc-r, because r<cc.
r = cc - 1;
lcl_tSizeType r = cc - 1; // true row index
while ( r !=0 && cc-r < p )
{
fEliminate = aMatN[r][ cc - aShift[r] ];
double fEliminate = aMatN[r][ cc - aShift[r] ]; // used for the element, that will become zero
if ( fEliminate != 0.0) // else element is accidentally zero, no action needed
{
// row r -= fEliminate * row cc only relevant for right side
+1 -1
View File
@@ -309,7 +309,7 @@
<object class="GtkLabel" id="FT_RANGE">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes" context="tp_DataSource|FT_RANGE">Ran_ge for %VALUETYPE</property>
<property name="label" translatable="yes" context="tp_DataSource|FT_RANGE">Ran_ge</property>
<property name="use-underline">True</property>
<property name="mnemonic-widget">EDT_RANGE</property>
<property name="xalign">0</property>
+1
View File
@@ -117,6 +117,7 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\
comphelper/source/misc/hash \
comphelper/source/misc/instancelocker \
comphelper/source/misc/interaction \
comphelper/source/misc/invocationhelper \
comphelper/source/misc/logging \
comphelper/source/misc/lok \
comphelper/source/misc/mimeconfighelper \
+243
View File
@@ -0,0 +1,243 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* 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/.
*/
#include <sal/config.h>
#include <comphelper/invocationhelper.hxx>
#include <com/sun/star/beans/MethodConcept.hpp>
#include <com/sun/star/beans/PropertyConcept.hpp>
#include <com/sun/star/beans/theIntrospection.hpp>
#include <com/sun/star/beans/XIntrospectionAccess.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/NoSuchElementException.hpp>
#include <com/sun/star/lang/NoSuchMethodException.hpp>
#include <com/sun/star/script/CannotConvertException.hpp>
#include <com/sun/star/script/Converter.hpp>
#include <com/sun/star/script/XInvocation.hpp>
namespace comphelper
{
constexpr sal_Int32 ALLOWED_METHODS
= css::beans::MethodConcept::ALL ^ css::beans::MethodConcept::DANGEROUS;
constexpr sal_Int32 ALLOWED_PROPERTIES
= css::beans::PropertyConcept::ALL ^ css::beans::PropertyConcept::DANGEROUS;
InvocationHelper::InvocationHelper(const css::uno::Reference<css::uno::XComponentContext>& xContext)
: m_xContext(xContext)
{
}
css::uno::Reference<css::beans::XIntrospectionAccess>
InvocationHelper::getIntrospection(css::script::XInvocation* pInvocation)
{
ensureIntrospection(pInvocation);
return m_xIntrospectionAccess;
}
css::uno::Sequence<css::uno::Any> InvocationHelper::prepareInvokeParams(
const css::uno::Sequence<css::uno::Any>& aParams,
const css::uno::Sequence<css::reflection::ParamInfo>& aParamInfos)
{
css::uno::Sequence<css::uno::Any> aInvokeParams(aParamInfos.getLength());
css::uno::Any* pInvokeParams = aInvokeParams.getArray();
for (sal_Int32 nParam = 0, nParams = aParamInfos.getLength(); nParam < nParams; ++nParam)
{
const css::reflection::ParamInfo& rParam = aParamInfos[nParam];
if (rParam.aMode == css::reflection::ParamMode_OUT)
{
// Initialize default value if the parameter is OUT
rParam.aType->createObject(pInvokeParams[nParam]);
}
else
{
css::uno::Type aDestType(rParam.aType->getTypeClass(), rParam.aType->getName());
try
{
pInvokeParams[nParam] = m_xTypeConverter->convertTo(aParams[nParam], aDestType);
}
catch (css::script::CannotConvertException& e)
{
// Add optional parameter index
e.ArgumentIndex = nParam;
throw;
}
}
}
return aInvokeParams;
}
css::uno::Any InvocationHelper::invoke(css::script::XInvocation* pInvocation,
const OUString& aFunctionName,
const css::uno::Sequence<css::uno::Any>& aParams,
css::uno::Sequence<sal_Int16>& aOutParamIndex,
css::uno::Sequence<css::uno::Any>& aOutParam)
{
// This implementation is heavily inspired by Invocation_Impl::invoke
ensureIntrospection(pInvocation);
css::uno::Reference<css::reflection::XIdlMethod> xMethod;
try
{
xMethod = m_xIntrospectionAccess->getMethod(aFunctionName, ALLOWED_METHODS);
}
catch (css::lang::NoSuchMethodException&)
{
throw css::lang::IllegalArgumentException(u"no such method"_ustr, pInvocation, 0);
}
css::uno::Sequence<css::reflection::ParamInfo> aParamInfos = xMethod->getParameterInfos();
if (aParams.getLength() != aParamInfos.getLength())
{
throw css::lang::IllegalArgumentException(
"incorrect number of parameters passed invoking function " + aFunctionName
+ ": expected " + OUString::number(aParamInfos.getLength()) + ", got "
+ OUString::number(aParams.getLength()),
pInvocation, 1);
}
ensureTypeConverter();
css::uno::Sequence<css::uno::Any> aInvokeParams = prepareInvokeParams(aParams, aParamInfos);
css::uno::Reference<css::script::XInvocation> xInvocation(pInvocation);
css::uno::Any aRet = xMethod->invoke(css::uno::Any(xInvocation), aInvokeParams);
size_t nOutParams = std::count_if(
std::cbegin(aParamInfos), std::cend(aParamInfos),
[](const auto& rParamInfo) { return rParamInfo.aMode != css::reflection::ParamMode_IN; });
aOutParamIndex.realloc(nOutParams);
aOutParam.realloc(nOutParams);
sal_Int16* pOutParamIndex = aOutParamIndex.getArray();
css::uno::Any* pOutParam = aOutParam.getArray();
for (sal_Int32 nParam = 0, nOutParam = 0, nParams = aParamInfos.getLength(); nParam < nParams;
++nParam)
{
if (aParamInfos[nParam].aMode == css::reflection::ParamMode_IN)
continue;
pOutParamIndex[nOutParam] = nParam;
pOutParam[nOutParam] = aInvokeParams[nParam];
nOutParam++;
}
return aRet;
}
void InvocationHelper::setValue(css::script::XInvocation* pInvocation,
const OUString& aPropertyName, const css::uno::Any& aValue)
{
ensureIntrospection(pInvocation);
css::uno::Reference<css::beans::XPropertySet> xPropertySet(m_xIntrospectionAccess,
css::uno::UNO_QUERY);
if (!xPropertySet.is())
throw css::beans::UnknownPropertyException(aPropertyName);
css::beans::Property aProp;
try
{
aProp = m_xIntrospectionAccess->getProperty(aPropertyName, ALLOWED_PROPERTIES);
}
catch (css::container::NoSuchElementException&)
{
throw css::beans::UnknownPropertyException(aPropertyName);
}
ensureTypeConverter();
css::uno::Any aConvertedValue = m_xTypeConverter->convertTo(aValue, aProp.Type);
try
{
return xPropertySet->setPropertyValue(aPropertyName, aConvertedValue);
}
catch (css::lang::WrappedTargetException& e)
{
throw css::reflection::InvocationTargetException(e.Message, pInvocation, e.TargetException);
}
catch (css::beans::PropertyVetoException& e)
{
throw css::reflection::InvocationTargetException(e.Message, pInvocation, css::uno::Any(e));
}
}
css::uno::Any InvocationHelper::getValue(css::script::XInvocation* pInvocation,
const OUString& aPropertyName)
{
// Make sure the introspection access implements XPropertySet and that the property is one of
// the ones allowed by hasProperty.
if (!hasProperty(pInvocation, aPropertyName))
throw css::beans::UnknownPropertyException(aPropertyName);
css::uno::Reference<css::beans::XPropertySet> xPropertySet(m_xIntrospectionAccess,
css::uno::UNO_QUERY_THROW);
try
{
return xPropertySet->getPropertyValue(aPropertyName);
}
catch (css::lang::WrappedTargetException& e)
{
throw css::reflection::InvocationTargetException(e.Message, pInvocation, e.TargetException);
}
}
sal_Bool InvocationHelper::hasMethod(css::script::XInvocation* pInvocation, const OUString& aName)
{
ensureIntrospection(pInvocation);
return m_xIntrospectionAccess->hasMethod(aName, ALLOWED_METHODS);
}
sal_Bool InvocationHelper::hasProperty(css::script::XInvocation* pInvocation, const OUString& aName)
{
ensureIntrospection(pInvocation);
css::uno::Reference<css::beans::XPropertySet> xPropertySet(m_xIntrospectionAccess,
css::uno::UNO_QUERY);
return xPropertySet.is() && m_xIntrospectionAccess->hasProperty(aName, ALLOWED_PROPERTIES);
}
void InvocationHelper::ensureTypeConverter()
{
if (m_xTypeConverter.is())
return;
m_xTypeConverter = css::script::Converter::create(m_xContext);
}
void InvocationHelper::ensureIntrospection(css::script::XInvocation* pInvocation)
{
if (m_xIntrospectionAccess.is())
return;
css::uno::Reference<css::beans::XIntrospection> xIntrospection
= css::beans::theIntrospection::get(m_xContext);
css::uno::Reference<css::script::XInvocation> xInvocation(pInvocation);
m_xIntrospectionAccess = xIntrospection->inspect(css::uno::Any(xInvocation));
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
+20
View File
@@ -115,6 +115,26 @@ public:
return ret;
}
bool TraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr)
{
// The C++ definition of assert in glibc 2.44 checks that its argument is a single
// expression with `1 ? 1 : bool (__VA_ARGS__)`, which re-evaluates the whole argument in a
// branch that is never taken; do not descend into that dead branch to avoid duplicate
// warnings:
if (expr->getType()->isBooleanType())
{
auto const loc = expr->getBeginLoc();
if (compiler.getSourceManager().isMacroBodyExpansion(loc)
&& Lexer::getImmediateMacroName(loc, compiler.getSourceManager(),
compiler.getLangOpts())
== "assert")
{
return true;
}
}
return FilteringPlugin::TraverseCXXFunctionalCastExpr(expr);
}
bool VisitImplicitCastExpr(ImplicitCastExpr const* expr)
{
if (ignoreLocation(expr))
@@ -241,15 +241,7 @@ public:
FilteringPlugin(data) {}
virtual void run() override
{
std::string fn(handler.getMainFileName());
loplugin::normalizeDotDotInFilePath(fn);
if (loplugin::hasPathnamePrefix(fn, SRCDIR "/soltools/cpp")
|| loplugin::hasPathnamePrefix(fn, SRCDIR "/soltools/mkdepend"))
return;
TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
}
{ TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
bool TraverseCallExpr(CallExpr * expr);
@@ -488,6 +480,18 @@ bool ImplicitBoolConversion::TraverseCXXStaticCastExpr(CXXStaticCastExpr * expr)
bool ImplicitBoolConversion::TraverseCXXFunctionalCastExpr(
CXXFunctionalCastExpr * expr)
{
// The C++ definition of assert in glibc 2.44 checks that its argument is a single expression
// with `1 ? 1 : bool (__VA_ARGS__)`, which re-evaluates the whole argument in a branch that is
// never taken; do not descend into that dead branch to avoid duplicate warnings:
if (expr->getType()->isBooleanType()) {
auto const loc = expr->getBeginLoc();
if (compiler.getSourceManager().isMacroBodyExpansion(loc)
&& Lexer::getImmediateMacroName(
loc, compiler.getSourceManager(), compiler.getLangOpts()) == "assert")
{
return true;
}
}
nested.push(std::vector<ImplicitCastExpr const *>());
bool bRet = RecursiveASTVisitor::TraverseCXXFunctionalCastExpr(expr);
assert(!nested.empty());
@@ -721,6 +725,15 @@ bool ImplicitBoolConversion::VisitImplicitCastExpr(
}
}
}
// Ignore the conversion from bool to int in the `1 ? 1 : bool (__VA_ARGS__)` argument check
// of the C++ definition of assert in glibc 2.44:
auto const loc = expr->getBeginLoc();
if (compiler.getSourceManager().isMacroBodyExpansion(loc)
&& Lexer::getImmediateMacroName(
loc, compiler.getSourceManager(), compiler.getLangOpts()) == "assert")
{
return true;
}
if (nested.empty()) {
reportWarning(expr);
} else {
@@ -757,6 +770,13 @@ bool ImplicitBoolConversion::VisitImplicitCastExpr(
&& !calls.empty())
{
CallExpr const * call = calls.top();
// Ignore the conversion from pointer in the `extern _Bool __assert_single_arg (_Bool)`
// check in the C definition of assert in glibc 2.44:
if (auto const fd = call->getDirectCallee()) {
if (fd->getIdentifier() && fd->getName() == "__assert_single_arg") {
return true;
}
}
if (std::any_of(
call->arg_begin(), call->arg_end(),
[expr](Expr const * e) { return expr == e->IgnoreParens(); }))
+36 -6
View File
@@ -45,6 +45,9 @@ public:
bool PreTraverseFunctionDecl(FunctionDecl* decl);
bool PostTraverseFunctionDecl(FunctionDecl* decl, bool);
bool TraverseFunctionDecl(FunctionDecl* decl);
bool PreTraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr);
bool PostTraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr, bool);
bool TraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr);
bool VisitCallExpr(CallExpr const*);
private:
@@ -76,14 +79,36 @@ bool PointerBool::TraverseFunctionDecl(FunctionDecl* decl)
return ret;
}
bool PointerBool::PreTraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr)
{
// The C++ definition of assert in glibc 2.44 checks that its argument is a single expression
// with `1 ? 1 : bool (__VA_ARGS__)`, which re-evaluates the whole argument in a branch that is
// never taken; do not descend into that dead branch to avoid duplicate warnings:
if (!expr->getType()->isBooleanType())
{
return true;
}
auto const loc = expr->getBeginLoc();
return !compiler.getSourceManager().isMacroBodyExpansion(loc)
|| Lexer::getImmediateMacroName(loc, compiler.getSourceManager(), compiler.getLangOpts())
!= "assert";
}
bool PointerBool::PostTraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr*, bool) { return true; }
bool PointerBool::TraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr)
{
bool ret = true;
if (PreTraverseCXXFunctionalCastExpr(expr))
{
ret = FilteringPlugin::TraverseCXXFunctionalCastExpr(expr);
PostTraverseCXXFunctionalCastExpr(expr, ret);
}
return ret;
}
bool PointerBool::VisitCallExpr(CallExpr const* callExpr)
{
std::string fn(handler.getMainFileName());
loplugin::normalizeDotDotInFilePath(fn);
if (loplugin::hasPathnamePrefix(fn, SRCDIR "/soltools/cpp")
|| loplugin::hasPathnamePrefix(fn, SRCDIR "/soltools/mkdepend"))
return true;
if (ignoreLocation(callExpr))
return true;
// TODO this doesn't currently work, the args and the params don't seem to line up
@@ -100,6 +125,11 @@ bool PointerBool::VisitCallExpr(CallExpr const* callExpr)
}
if (!functionDecl)
return true;
// glibc 2.44 checks that the argument to assert is a single expression by passing it to
// "extern _Bool __assert_single_arg (_Bool)" inside a sizeof. A pointer argument to that
// internal check is not a mistake in the calling code:
if (functionDecl->getIdentifier() && functionDecl->getName() == "__assert_single_arg")
return true;
unsigned len = std::min(callExpr->getNumArgs(), functionDecl->getNumParams());
for (unsigned i = 0; i < len; ++i)
+17
View File
@@ -132,6 +132,23 @@ public:
return ret;
}
bool TraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr * expr) {
// The C++ definition of assert in glibc 2.44 checks that its argument is a single
// expression with `1 ? 1 : bool (__VA_ARGS__)`, which re-evaluates the whole argument in a
// branch that is never taken; do not descend into that dead branch to avoid duplicate
// warnings:
if (expr->getType()->isBooleanType()) {
auto const loc = expr->getBeginLoc();
if (compiler.getSourceManager().isMacroBodyExpansion(loc)
&& Lexer::getImmediateMacroName(
loc, compiler.getSourceManager(), compiler.getLangOpts()) == "assert")
{
return true;
}
}
return FilteringRewritePlugin::TraverseCXXFunctionalCastExpr(expr);
}
bool VisitImplicitCastExpr(ImplicitCastExpr const * expr);
bool VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr);
@@ -64,6 +64,8 @@ int main()
}
// expected-error@+1 {{implicit conversion of constant &"msg"[0] of type 'const char *' to 'bool'; use 'true' instead [loplugin:consttobool]}}
assert("msg");
// expected-error@+1 {{implicit conversion of constant 2 of type 'int' to 'bool'; use 'true' instead [loplugin:consttobool]}}
assert(2);
#endif
}
@@ -11,6 +11,7 @@
#include <array>
#include <atomic>
#include <cassert>
#include <initializer_list>
#include <com/sun/star/uno/Sequence.hxx>
@@ -80,4 +81,13 @@ void f()
s8[0] = false;
}
void testAssert([[maybe_unused]] bool b, [[maybe_unused]] int n)
{
assert(b);
#if !defined NDEBUG
// expected-error@+1 {{implicit conversion (IntegralCast) from 'bool' to 'int' [loplugin:implicitboolconversion]}}
assert(n = b);
#endif
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
@@ -7,6 +7,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <sal/config.h>
#include <cassert>
#include <sal/types.h>
#include <com/sun/star/uno/Sequence.hxx>
@@ -43,4 +47,16 @@ void test2(int p1)
func_bool_via_forward_template(p1);
}
// expected-note@+1 {{method here [loplugin:pointerbool]}}
bool func_boolA(bool);
void testAssert([[maybe_unused]] int* p)
{
assert(p);
#if !defined NDEBUG
// expected-error@+1 {{possibly unwanted implicit conversion when calling bool param [loplugin:pointerbool]}}
assert(func_boolA(p));
#endif
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
@@ -9,6 +9,7 @@
#include <sal/config.h>
#include <cassert>
#include <cstddef>
#include <sal/types.h>
@@ -485,6 +486,14 @@ void testFunctionalCast2() {
S1 aTest2(S1_COL);
}
void testAssert([[maybe_unused]] int n) {
assert(n > 0);
#if !defined NDEBUG
// expected-error@+1 {{redundant functional cast from 'bool' to 'bool' [loplugin:redundantcast]}}
assert(bool(n > 0));
#endif
}
int main() {
testConstCast();
testStaticCast();
+1 -1
View File
@@ -38,8 +38,8 @@
#define WITH_LOCALE_hu 0
#define WITH_LOCALE_is 0
#define WITH_LOCALE_ja 0
#define WITH_LOCALE_kmr_Latn 0
#define WITH_LOCALE_ko 0
#define WITH_LOCALE_ku 0
#define WITH_LOCALE_ln 0
#define WITH_LOCALE_my 0
#define WITH_LOCALE_ne 0
+8 -5
View File
@@ -1108,8 +1108,6 @@ cygwin*|wsl*)
DLLPOST=".dll"
LINKFLAGSNOUNDEFS=
# bypass check for ninja, it is not in default path, but it can be used nevertheless by default
NINJA="assumed to be available from Visual Studio"
if test "$host_cpu" = "aarch64"; then
build_skia=yes
@@ -1498,6 +1496,7 @@ if test "$_os" != "WINNT"; then
# Clang 12.0.1 occasionally SEGVs on some of the test invocations during AC_PROG_CC with -O2):
save_CFLAGS=$CFLAGS
CFLAGS=-g
ac_cv_prog_cc_c23=no
AC_PROG_CC
CFLAGS=$save_CFLAGS
if test -z "$CC_BASE"; then
@@ -4758,6 +4757,10 @@ if test "$_os" = "WINNT"; then
PathFormat "$VC_PRODUCT_DIR/../Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/cmake.exe"
CMAKE="$formatted_path"
# Find the ninja that ships with Visual Studio, beside that cmake.
PathFormat "$VC_PRODUCT_DIR/../Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe"
NINJA="$formatted_path"
# Find the version of devenv.exe
PathFormat "$VC_PRODUCT_DIR/../Common7/IDE/devenv.exe"
DEVENV="$formatted_path"
@@ -10641,9 +10644,9 @@ else
fi
if test "$COM" = "MSC"; then
if test "$MSVC_USE_DEBUG_RUNTIME" = TRUE; then
LIBXML_LIBS="${WORKDIR}/UnpackedTarball/libxml2/Debug/libxml2d.lib"
LIBXML_LIBS="${WORKDIR}/UnpackedTarball/libxml2/libxml2d.lib"
else
LIBXML_LIBS="${WORKDIR}/UnpackedTarball/libxml2/Release/libxml2.lib"
LIBXML_LIBS="${WORKDIR}/UnpackedTarball/libxml2/libxml2.lib"
fi
else
LIBXML_LIBS="-L${WORKDIR}/UnpackedTarball/libxml2/.libs -lxml2"
@@ -15020,7 +15023,7 @@ if test "$need_meson" = "yes"; then
fi
fi
if test -z "$NINJA" || test "$NINJA" = 'assumed to be available from Visual Studio'; then
if test -z "$NINJA"; then
x_NINJA=[\#]
else
x_NINJA=
@@ -52,6 +52,19 @@ public:
void test_toDateTime_date_only();
void test_toDateTime_with_nanoseconds();
// toTimeString / toDateTimeString tests
void test_toTimeString_no_fraction_when_zero_nanoseconds();
void test_toTimeString_keeps_full_precision();
void test_toDateTimeString_no_fraction_when_zero_nanoseconds();
// fractional-seconds rounding for SQL literal generation
void test_roundTimeFraction_rounds_to_4_digits();
void test_roundTimeFraction_carries_into_seconds();
void test_roundTimeFraction_wraps_at_midnight();
void test_roundDateTimeFraction_carries_into_next_day();
void test_roundDateTimeFraction_rolls_over_month_end();
void test_roundTimeFraction_noop_when_no_cap_requested();
CPPUNIT_TEST_SUITE(DBTypeConversionTest);
CPPUNIT_TEST(test_toDate_basic);
@@ -66,6 +79,17 @@ public:
CPPUNIT_TEST(test_toDateTime_date_only);
CPPUNIT_TEST(test_toDateTime_with_nanoseconds);
CPPUNIT_TEST(test_toTimeString_no_fraction_when_zero_nanoseconds);
CPPUNIT_TEST(test_toTimeString_keeps_full_precision);
CPPUNIT_TEST(test_toDateTimeString_no_fraction_when_zero_nanoseconds);
CPPUNIT_TEST(test_roundTimeFraction_rounds_to_4_digits);
CPPUNIT_TEST(test_roundTimeFraction_carries_into_seconds);
CPPUNIT_TEST(test_roundTimeFraction_wraps_at_midnight);
CPPUNIT_TEST(test_roundDateTimeFraction_carries_into_next_day);
CPPUNIT_TEST(test_roundDateTimeFraction_rolls_over_month_end);
CPPUNIT_TEST(test_roundTimeFraction_noop_when_no_cap_requested);
CPPUNIT_TEST_SUITE_END();
};
@@ -166,6 +190,118 @@ void DBTypeConversionTest::test_toDateTime_with_nanoseconds()
CPPUNIT_ASSERT_EQUAL_MESSAGE("NanoSeconds", sal_uInt32(500000000), aDT.NanoSeconds);
}
// ----- toTimeString / toDateTimeString ---------------------------------------
void DBTypeConversionTest::test_toTimeString_no_fraction_when_zero_nanoseconds()
{
// tdf#153057 (reopened): TIME values must not get trailing ".000000000"
css::util::Time aTime;
aTime.Hours = 0;
aTime.Minutes = 3;
aTime.Seconds = 0;
aTime.NanoSeconds = 0;
CPPUNIT_ASSERT_EQUAL(u"00:03:00"_ustr, DBTypeConversion::toTimeString(aTime));
}
void DBTypeConversionTest::test_toTimeString_keeps_full_precision()
{
css::util::Time aTime;
aTime.Hours = 0;
aTime.Minutes = 3;
aTime.Seconds = 0;
aTime.NanoSeconds = 123456789;
CPPUNIT_ASSERT_EQUAL(u"00:03:00.123456789"_ustr, DBTypeConversion::toTimeString(aTime));
}
void DBTypeConversionTest::test_roundTimeFraction_rounds_to_4_digits()
{
// this is the rounding the Firebird is using
css::util::Time aTime;
aTime.Hours = 0;
aTime.Minutes = 3;
aTime.Seconds = 0;
aTime.NanoSeconds = 123456789;
CPPUNIT_ASSERT(!DBTypeConversion::roundTimeFraction(aTime, 4));
// 123456789ns rounds to the nearest 1/10000s (123500000ns = .1235).
CPPUNIT_ASSERT_EQUAL(sal_uInt32(123500000), aTime.NanoSeconds);
// toTimeString() trims trailing zeros
CPPUNIT_ASSERT_EQUAL(u"00:03:00.1235"_ustr, DBTypeConversion::toTimeString(aTime));
}
void DBTypeConversionTest::test_roundTimeFraction_carries_into_seconds()
{
css::util::Time aTime;
aTime.Hours = 0;
aTime.Minutes = 3;
aTime.Seconds = 59;
aTime.NanoSeconds = 999960000; // rounds up to a full extra second
CPPUNIT_ASSERT(!DBTypeConversion::roundTimeFraction(aTime, 4));
CPPUNIT_ASSERT_EQUAL(u"00:04:00"_ustr, DBTypeConversion::toTimeString(aTime));
}
void DBTypeConversionTest::test_roundTimeFraction_wraps_at_midnight()
{
css::util::Time aTime;
aTime.Hours = 23;
aTime.Minutes = 59;
aTime.Seconds = 59;
aTime.NanoSeconds = 999950000;
CPPUNIT_ASSERT(DBTypeConversion::roundTimeFraction(aTime, 4));
CPPUNIT_ASSERT_EQUAL(u"00:00:00"_ustr, DBTypeConversion::toTimeString(aTime));
}
void DBTypeConversionTest::test_roundDateTimeFraction_carries_into_next_day()
{
css::util::DateTime aDT;
aDT.Year = 2024;
aDT.Month = 7;
aDT.Day = 15;
aDT.Hours = 23;
aDT.Minutes = 59;
aDT.Seconds = 59;
aDT.NanoSeconds = 999950000;
DBTypeConversion::roundDateTimeFraction(aDT, 4);
CPPUNIT_ASSERT_EQUAL(u"2024-07-16 00:00:00"_ustr, DBTypeConversion::toDateTimeString(aDT));
}
void DBTypeConversionTest::test_roundDateTimeFraction_rolls_over_month_end()
{
css::util::DateTime aDT;
aDT.Year = 2024;
aDT.Month = 12;
aDT.Day = 31;
aDT.Hours = 23;
aDT.Minutes = 59;
aDT.Seconds = 59;
aDT.NanoSeconds = 999950000;
DBTypeConversion::roundDateTimeFraction(aDT, 4);
CPPUNIT_ASSERT_EQUAL(u"2025-01-01 00:00:00"_ustr, DBTypeConversion::toDateTimeString(aDT));
}
void DBTypeConversionTest::test_roundTimeFraction_noop_when_no_cap_requested()
{
css::util::Time aTime;
aTime.Hours = 0;
aTime.Minutes = 3;
aTime.Seconds = 0;
aTime.NanoSeconds = 123456789;
CPPUNIT_ASSERT(!DBTypeConversion::roundTimeFraction(aTime, 9));
CPPUNIT_ASSERT_EQUAL(sal_uInt32(123456789), aTime.NanoSeconds);
}
void DBTypeConversionTest::test_toDateTimeString_no_fraction_when_zero_nanoseconds()
{
css::util::DateTime aDT;
aDT.Year = 2024;
aDT.Month = 7;
aDT.Day = 15;
aDT.Hours = 14;
aDT.Minutes = 30;
aDT.Seconds = 0;
aDT.NanoSeconds = 0;
CPPUNIT_ASSERT_EQUAL(u"2024-07-15 14:30:00"_ustr, DBTypeConversion::toDateTimeString(aDT));
}
CPPUNIT_TEST_SUITE_REGISTRATION(DBTypeConversionTest);
} // namespace connectivity::commontools
@@ -75,6 +75,13 @@
<node oor:name="Features">
</node><!--Features-->
<node oor:name="MetaData">
<!-- Firebird's native TIME/TIMESTAMP precision is 1/10000s; it rejects a SQL
literal with more fractional-seconds digits than that (tdf#153057). -->
<node oor:name="MaxDateTimeLiteralFractionDigits" oor:op="replace">
<prop oor:name="Value" oor:type="xs:int">
<value>4</value>
</prop>
</node>
</node>
</node>
<!-- Firebird EXTERNAL Driver -->
@@ -129,6 +136,13 @@
<value>UserPassword</value>
</prop>
</node>
<!-- Firebird's native TIME/TIMESTAMP precision is 1/10000s; it rejects a SQL
literal with more fractional-seconds digits than that (tdf#153057). -->
<node oor:name="MaxDateTimeLiteralFractionDigits" oor:op="replace">
<prop oor:name="Value" oor:type="xs:int">
<value>4</value>
</prop>
</node>
</node>
</node>
</node>
@@ -18,6 +18,7 @@
*/
#include <connectivity/dbconversion.hxx>
#include <connectivity/dbmetadata.hxx>
#include <connectivity/dbtools.hxx>
#include <com/sun/star/script/XTypeConverter.hpp>
#include <com/sun/star/sdbc/DataType.hpp>
@@ -32,6 +33,7 @@
#include <comphelper/numbers.hxx>
#include <comphelper/types.hxx>
#include <rtl/ustrbuf.hxx>
#include <tuple>
#include <sal/log.hxx>
#include <comphelper/diagnose_ex.hxx>
@@ -48,7 +50,8 @@ using namespace ::com::sun::star::util;
using namespace ::com::sun::star::uno;
OUString DBTypeConversion::toSQLString(sal_Int32 eType, const Any& _rVal,
const Reference< XTypeConverter >& _rxTypeConverter)
const Reference< XTypeConverter >& _rxTypeConverter,
const Reference< XConnection >& _rxConnection)
{
OUStringBuffer aRet;
if (_rVal.hasValue())
@@ -125,6 +128,10 @@ OUString DBTypeConversion::toSQLString(sal_Int32 eType, const Any& _rVal,
// check if this is really a timestamp or only a date
if ( bOk )
{
// This is a SQL literal, so cap the fraction to what
// _rxConnection's backend can parse (tdf#153057).
DBTypeConversion::roundDateTimeFraction(aDateTime,
::dbtools::DatabaseMetaData(_rxConnection).getMaxDateTimeLiteralFractionDigits());
aRet.append("{ts '"
+ DBTypeConversion::toDateTimeString(aDateTime)
+ "'}");
@@ -178,6 +185,10 @@ OUString DBTypeConversion::toSQLString(sal_Int32 eType, const Any& _rVal,
else
bOk = _rVal >>= aTime;
OSL_ENSURE( bOk,"DBTypeConversion::toSQLString: _rVal is not time!");
// See the TIMESTAMP case above.
// Discarding the day-carry return: this is just a Time.
std::ignore = DBTypeConversion::roundTimeFraction(aTime,
::dbtools::DatabaseMetaData(_rxConnection).getMaxDateTimeLiteralFractionDigits());
aRet.append("{t '"
+ DBTypeConversion::toTimeString(aTime)
+ "'}");
@@ -26,6 +26,7 @@
#include <sal/log.hxx>
#include <unotools/datetime.hxx>
#include <comphelper/date.hxx>
#include <o3tl/safeint.hxx>
#include <o3tl/string_view.hxx>
#include <sstream>
#include <iomanip>
@@ -100,8 +101,18 @@ namespace dbtools
ostr.fill('0');
ostr << setw(2) << rTime.Hours << ":"
<< setw(2) << rTime.Minutes << ":"
<< setw(2) << rTime.Seconds << "."
<< setw(9) << rTime.NanoSeconds;
<< setw(2) << rTime.Seconds;
if (rTime.NanoSeconds)
{
std::ostringstream ostrFraction;
ostrFraction.fill('0');
ostrFraction << setw(9) << rTime.NanoSeconds;
// Trim trailing zeros if exist, since some backends (e.g. Firebird)
// reject a literal with more fractional digits than they support.
std::string sFraction = ostrFraction.str();
sFraction.erase(sFraction.find_last_not_of('0') + 1);
ostr << "." << sFraction;
}
return OUString::createFromAscii(ostr.str());
}
@@ -113,6 +124,43 @@ namespace dbtools
return toDateString(aDate) + " " + toTimeString(aTime);
}
bool DBTypeConversion::roundTimeFraction(css::util::Time& rTime, sal_Int32 nMaxFractionDigits)
{
// Round the fraction to at most nMaxFractionDigits digits,
// carrying into seconds/minutes/hours as needed.
if (nMaxFractionDigits >= 9 || nMaxFractionDigits < 0)
return false;
sal_uInt32 nRoundingUnit = 1;
for (sal_Int32 i = 0; i < 9 - nMaxFractionDigits; ++i)
nRoundingUnit *= 10;
sal_uInt32 nNanoSeconds
= ((rTime.NanoSeconds + nRoundingUnit / 2) / nRoundingUnit) * nRoundingUnit;
bool bCarriedPastMidnight = false;
if (nNanoSeconds >= o3tl::make_unsigned(nanoSecInSec))
{
nNanoSeconds -= static_cast<sal_uInt32>(nanoSecInSec);
if (++rTime.Seconds >= secInMin)
{
rTime.Seconds -= secInMin;
if (++rTime.Minutes >= minInHour)
{
rTime.Minutes -= minInHour;
// Time has no day of its own to carry into so wrap
// at 24h and report it to the caller.
if (++rTime.Hours >= 24)
{
rTime.Hours -= 24;
bCarriedPastMidnight = true;
}
}
}
}
rTime.NanoSeconds = nNanoSeconds;
return bCarriedPastMidnight;
}
css::util::Date DBTypeConversion::toDate(const sal_Int32 _nVal)
{
css::util::Date aReturn;
@@ -221,6 +269,27 @@ namespace dbtools
comphelper::date::convertDaysToDate( nTempDays, _rDate.Day, _rDate.Month, _rDate.Year );
}
void DBTypeConversion::roundDateTimeFraction(css::util::DateTime& rDateTime, sal_Int32 nMaxFractionDigits)
{
css::util::Time aTime(rDateTime.NanoSeconds, rDateTime.Seconds, rDateTime.Minutes,
rDateTime.Hours, rDateTime.IsUTC);
if (roundTimeFraction(aTime, nMaxFractionDigits))
{
// Unlike a bare Time, a DateTime does have a date to carry into,
// so 23:59:59.99995 becomes the next day at 00:00:00 rather than
// an out-of-range 24:00:00 on the original date.
css::util::Date aDate(rDateTime.Day, rDateTime.Month, rDateTime.Year);
addDays(1, aDate);
rDateTime.Day = aDate.Day;
rDateTime.Month = aDate.Month;
rDateTime.Year = aDate.Year;
}
rDateTime.Hours = aTime.Hours;
rDateTime.Minutes = aTime.Minutes;
rDateTime.Seconds = aTime.Seconds;
rDateTime.NanoSeconds = aTime.NanoSeconds;
}
static void subDays(const sal_Int32 nDays, css::util::Date& _rDate )
{
sal_Int64 nTempDays = implRelativeToAbsoluteNull(_rDate);
@@ -300,6 +300,24 @@ namespace dbtools
return doGenerate;
}
sal_Int32 DatabaseMetaData::getMaxDateTimeLiteralFractionDigits() const
{
if ( !isConnected() )
return 4; // fallback for a caller with no connection info
sal_Int32 nDigits( 9 );
Any setting;
if ( lcl_getDriverSetting( u"MaxDateTimeLiteralFractionDigits"_ustr, *m_pImpl, setting ) )
{
if( ! (setting >>= nDigits) )
{
SAL_WARN("connectivity.commontools", "getMaxDateTimeLiteralFractionDigits: unable to assign MaxDateTimeLiteralFractionDigits");
nDigits = 4;
}
}
return nDigits;
}
bool DatabaseMetaData::shouldSubstituteParameterNames() const
{
bool doSubstitute( true );
@@ -128,7 +128,7 @@ namespace dbtools
std::unique_ptr<OSQLParseNode> OPredicateInputController::implPredicateTree(OUString& _rErrorMessage, const OUString& _rStatement, const Reference< XPropertySet > & _rxField) const
{
std::unique_ptr<OSQLParseNode> pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, _rStatement, m_xFormatter, _rxField );
std::unique_ptr<OSQLParseNode> pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, _rStatement, m_xFormatter, _rxField, /*bUseRealName*/true, m_xConnection );
if ( !pReturn )
{ // is it a text field ?
sal_Int32 nType = DataType::OTHER;
@@ -149,7 +149,7 @@ namespace dbtools
{
sQuoted = u"'" + sQuoted.replaceAll(u"'", u"''") + u"'";
}
pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, sQuoted, m_xFormatter, _rxField );
pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, sQuoted, m_xFormatter, _rxField, /*bUseRealName*/true, m_xConnection );
}
// one more fallback: for numeric fields, and value strings containing a decimal/thousands separator
@@ -215,7 +215,7 @@ namespace dbtools
sTranslated = sTranslated.replace( nCtxThdSep, nFmtThdSep );
sTranslated = sTranslated.replace( nIntermediate, nFmtDecSep );
pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, sTranslated, m_xFormatter, _rxField );
pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, sTranslated, m_xFormatter, _rxField, /*bUseRealName*/true, m_xConnection );
}
}
}
@@ -966,9 +966,9 @@ void SAL_CALL OPreparedStatement::setBytes(sal_Int32 nParameterIndex,
setParameterNull(nParameterIndex, false);
const sal_Int32 nMaxSize = 0xFFFF;
const sal_uInt16 nSize = std::min(xBytes.getLength(), nMaxSize);
// 8000 corresponds to value from lcl_addDefaultParameters
// in dbaccess/source/filter/hsqldb/createparser.cxx
if (nSize > 8000)
// sqldata was allocated from sqllen in mallocSQLVAR, so grow it whenever the value is
// longer than the column it is bound to.
if (nSize > pVar->sqllen)
{
free(pVar->sqldata);
pVar->sqldata = static_cast<char *>(malloc(sizeof(char) * nSize + 2));
+23 -1
View File
@@ -57,6 +57,7 @@
#include <functional>
#include <memory>
#include <string_view>
#include <tuple>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
@@ -214,6 +215,14 @@ OUString OSQLParseNode::convertDateString(const SQLParseNodeParameter& rParam, s
OUString OSQLParseNode::convertDateTimeString(const SQLParseNodeParameter& rParam, const OUString& rString)
{
DateTime aDate = DBTypeConversion::toDateTime(rString);
// round here in case of re-normalization on a rounded value
if (aDate.NanoSeconds)
{
DBTypeConversion::roundDateTimeFraction(aDate, rParam.aMetaData.getMaxDateTimeLiteralFractionDigits());
return DBTypeConversion::toDateTimeString(aDate);
}
Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier());
Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY);
@@ -226,6 +235,15 @@ OUString OSQLParseNode::convertDateTimeString(const SQLParseNodeParameter& rPara
OUString OSQLParseNode::convertTimeString(const SQLParseNodeParameter& rParam, std::u16string_view rString)
{
css::util::Time aTime = DBTypeConversion::toTime(rString);
// Same fallback as convertDateTimeString() above
if (aTime.NanoSeconds)
{
// Discarding the day-carry return: only time is relevant here
std::ignore = DBTypeConversion::roundTimeFraction(aTime, rParam.aMetaData.getMaxDateTimeLiteralFractionDigits());
return DBTypeConversion::toTimeString(aTime);
}
Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier());
Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY);
@@ -1081,6 +1099,7 @@ OSQLParseNode* OSQLParser::buildNode_Date(const double& fValue, sal_Int32 nType)
case DataType::TIME:
{
css::util::Time aTime = DBTypeConversion::toTime(fValue);
std::ignore = DBTypeConversion::roundTimeFraction(aTime, m_aMetaData.getMaxDateTimeLiteralFractionDigits());
OUString aString = DBTypeConversion::toTimeString(aTime);
pDateNode->append(new OSQLInternalNode("", SQLNodeType::Keyword, SQL_TOKEN_T));
pDateNode->append(new OSQLInternalNode(aString, SQLNodeType::String));
@@ -1089,6 +1108,7 @@ OSQLParseNode* OSQLParser::buildNode_Date(const double& fValue, sal_Int32 nType)
case DataType::TIMESTAMP:
{
DateTime aDateTime = DBTypeConversion::toDateTime(fValue,DBTypeConversion::getNULLDate(m_xFormatter->getNumberFormatsSupplier()));
DBTypeConversion::roundDateTimeFraction(aDateTime, m_aMetaData.getMaxDateTimeLiteralFractionDigits());
if (aDateTime.Seconds || aDateTime.Minutes || aDateTime.Hours)
{
OUString aString = DBTypeConversion::toDateTimeString(aDateTime);
@@ -1176,7 +1196,8 @@ std::mutex& OSQLParser::getMutex()
std::unique_ptr<OSQLParseNode> OSQLParser::predicateTree(OUString& rErrorMessage, const OUString& rStatement,
const Reference< css::util::XNumberFormatter > & xFormatter,
const Reference< XPropertySet > & xField,
bool bUseRealName)
bool bUseRealName,
const Reference< css::sdbc::XConnection >& xConnection)
{
// Guard the parsing
std::unique_lock aGuard(getMutex());
@@ -1187,6 +1208,7 @@ std::unique_ptr<OSQLParseNode> OSQLParser::predicateTree(OUString& rErrorMessage
// reset the parser
m_xField = xField;
m_xFormatter = xFormatter;
m_aMetaData = ::dbtools::DatabaseMetaData(xConnection);
if (m_xField.is())
{
+2 -2
View File
@@ -728,8 +728,8 @@ private:
DECL_LINK(OnMoreColorsClick, weld::Button&, void);
DECL_LINK(SelectPaletteLBHdl, weld::ComboBox&, void);
DECL_LINK(ActivatePaletteColorHdl, const Color&, void);
DECL_LINK(ActivateRecentColorHdl, const Color&, void);
DECL_LINK(ActivatePaletteColorHdl, int, void);
DECL_LINK(ActivateRecentColorHdl, int, void);
DECL_LINK( SelectColorModeHdl_Impl, weld::Toggleable&, void );
void UpdateToSelectedColor(const NamedColor& rNamedColor);
void ChangeColor(const NamedColor &rNewColor, bool bUpdatePreset = true);
+17 -16
View File
@@ -210,23 +210,23 @@ class SvxNumOptionsTabPage : public SfxTabPage
OUString m_sNumCharFmtName;
OUString m_sBulletCharFormatName;
Timer aInvalidateTimer;
Timer m_aInvalidateTimer;
std::unique_ptr<SvxNumRule> pActNum;
std::unique_ptr<SvxNumRule> pSaveNum;
std::unique_ptr<SvxNumRule> m_pActNum;
std::unique_ptr<SvxNumRule> m_pSaveNum;
Size aInitSize[SVX_MAX_NUM];
Size m_aInitSize[SVX_MAX_NUM];
ImplSVEvent* m_pLevelHdlEvent;
bool bLastWidthModified : 1;
bool bModified : 1;
bool bPreset : 1;
bool bAutomaticCharStyles: 1;
bool bHTMLMode : 1;
bool m_bLastWidthModified : 1;
bool m_bModified : 1;
bool m_bPreset : 1;
bool m_bAutomaticCharStyles : 1;
bool m_bHTMLMode : 1;
std::vector<OUString> aGrfNames;
vcl::Font aActBulletFont;
std::vector<OUString> m_aGrfNames;
vcl::Font m_aActBulletFont;
enum class NumberType {
SHOW_NUMBERING = 0,
@@ -234,11 +234,11 @@ class SvxNumOptionsTabPage : public SfxTabPage
SHOW_BITMAP = 2,
NONE = 0xff
};
NumberType nBullet;
NumberType m_nBullet;
sal_uInt16 nActNumLvl;
TypedWhichId<SvxNumBulletItem> nNumItemId;
MapUnit eCoreUnit;
sal_uInt16 m_nActNumLvl;
TypedWhichId<SvxNumBulletItem> m_nNumItemId;
MapUnit m_eCoreUnit;
SvxRatioConnector m_aRatioTop;
SvxRatioConnector m_aRatioBottom;
@@ -289,7 +289,6 @@ class SvxNumOptionsTabPage : public SfxTabPage
DECL_LINK(NumberTypeSelectHdl_Impl, weld::ComboBox&, void);
DECL_LINK(LevelHdl_Impl, weld::ItemView&, void);
DECL_LINK(LevelHdl, void *, void);
DECL_LINK(PopupActivateHdl_Impl, weld::Toggleable&, void);
DECL_LINK(GraphicHdl_Impl, const OUString&, void);
DECL_LINK(BulletHdl_Impl, weld::Button&, void);
DECL_LINK(SizeHdl_Impl, weld::MetricSpinButton&, void);
@@ -306,6 +305,8 @@ class SvxNumOptionsTabPage : public SfxTabPage
DECL_LINK(PreviewInvalidateHdl_Impl, Timer*, void);
void EditModifyHdl_Impl(const weld::TextWidget*);
void CreateGalleryMenu();
public:
SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
virtual ~SvxNumOptionsTabPage() override;
+3
View File
@@ -177,6 +177,9 @@ class SvxParaAlignTabPage : public SfxTabPage
std::unique_ptr<weld::MetricSpinButton> m_xLetterSpacingMinimum;
std::unique_ptr<weld::MetricSpinButton> m_xLetterSpacingMaximum;
/// compound-based hyphenation
std::unique_ptr<weld::CheckButton> m_xCompoundBased;
/// glyph scaling
std::unique_ptr<weld::Label> m_xLabelGlyphScaling;
std::unique_ptr<weld::MetricSpinButton> m_xGlyphScalingMinimum;
+3 -2
View File
@@ -344,12 +344,13 @@ IMPL_LINK_NOARG( SvxDefaultColorOptPage, SelectPaletteLbHdl, weld::ComboBox&, vo
aPaletteManager.ReloadColorSet(m_aColorIconView);
}
IMPL_LINK(SvxDefaultColorOptPage, ColorActivatedHdl, const Color&, rColor, void)
IMPL_LINK(SvxDefaultColorOptPage, ColorActivatedHdl, int, nIndex, void)
{
sal_Int32 nIdx = m_xLbChartColors->get_selected_index();
if (nIdx != -1)
{
const XColorEntry aEntry(rColor, m_xLbChartColors->get_selected_text());
const XColorEntry aEntry(m_aColorIconView.getColor(nIndex),
m_xLbChartColors->get_selected_text());
ModifyColorEntry(aEntry, nIdx);
m_SvxChartColorTableUniquePtr->replace(nIdx, aEntry);
+1 -1
View File
@@ -53,7 +53,7 @@ private:
DECL_LINK(ResetToDefaults, weld::Button&, void);
DECL_LINK(AddChartColor, weld::Button&, void);
DECL_LINK(RemoveChartColor, weld::Button&, void);
DECL_LINK(ColorActivatedHdl, const Color&, void);
DECL_LINK(ColorActivatedHdl, int, void);
DECL_LINK(SelectPaletteLbHdl, weld::ComboBox&, void);
DECL_LINK(LbChartColorsSelectionChangedHdl, weld::ItemView&, void);
+183 -175
View File
@@ -1126,16 +1126,16 @@ IMPL_LINK_NOARG(SvxBitmapPickTabPage, ClickAddBrowseHdl_Impl, weld::Button&, voi
SvxNumOptionsTabPage::SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogController* pController,
const SfxItemSet& rSet)
: SfxTabPage(pPage, pController, u"cui/ui/numberingoptionspage.ui"_ustr, u"NumberingOptionsPage"_ustr, &rSet)
, aInvalidateTimer("cui SvxNumOptionsTabPage aInvalidateTimer")
, m_aInvalidateTimer("cui SvxNumOptionsTabPage aInvalidateTimer")
, m_pLevelHdlEvent(nullptr)
, bLastWidthModified(false)
, bModified(false)
, bPreset(false)
, bAutomaticCharStyles(true)
, bHTMLMode(false)
, nBullet(NumberType::NONE)
, nActNumLvl(1)
, nNumItemId(SID_ATTR_NUMBERING_RULE)
, m_bLastWidthModified(false)
, m_bModified(false)
, m_bPreset(false)
, m_bAutomaticCharStyles(true)
, m_bHTMLMode(false)
, m_nBullet(NumberType::NONE)
, m_nActNumLvl(1)
, m_nNumItemId(SID_ATTR_NUMBERING_RULE)
, m_aRatioTop(ConnectorType::Top)
, m_aRatioBottom(ConnectorType::Bottom)
, m_xGrid(m_xBuilder->weld_widget(u"grid2"_ustr))
@@ -1180,7 +1180,7 @@ SvxNumOptionsTabPage::SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogC
m_xBulRelSizeMF->set_min(SVX_NUM_REL_SIZE_MIN, FieldUnit::PERCENT);
m_xBulRelSizeMF->set_increments(5, 50, FieldUnit::PERCENT);
SetExchangeSupport();
aActBulletFont = lcl_GetDefaultBulletFont();
m_aActBulletFont = lcl_GetDefaultBulletFont();
// vertical alignment = fill makes the drawingarea expand the associated spinedits so we have to size it here
const sal_Int16 aHeight
= static_cast<sal_Int16>(std::max(int(m_xRatioCB->get_preferred_size().getHeight() / 2
@@ -1197,7 +1197,6 @@ SvxNumOptionsTabPage::SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogC
m_xBulletPB->connect_clicked(LINK(this, SvxNumOptionsTabPage, BulletHdl_Impl));
m_xFmtLB->connect_changed(LINK(this, SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl));
m_xBitmapMB->connect_selected(LINK(this, SvxNumOptionsTabPage, GraphicHdl_Impl));
m_xBitmapMB->connect_toggled(LINK(this, SvxNumOptionsTabPage, PopupActivateHdl_Impl));
m_xLevelLB->set_selection_mode(SelectionMode::Multiple);
m_xLevelLB->connect_selection_changed(LINK(this, SvxNumOptionsTabPage, LevelHdl_Impl));
m_xCharFmtLB->connect_changed(LINK(this, SvxNumOptionsTabPage, CharFmtHdl_Impl));
@@ -1213,10 +1212,12 @@ SvxNumOptionsTabPage::SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogC
m_xSameLevelCB->connect_toggled(LINK(this, SvxNumOptionsTabPage, SameLevelHdl_Impl));
m_xBulRelSizeMF->connect_value_changed(LINK(this,SvxNumOptionsTabPage, BulRelSizeHdl_Impl));
m_xBulColLB->SetSelectHdl(LINK(this, SvxNumOptionsTabPage, BulColorHdl_Impl));
aInvalidateTimer.SetInvokeHandler(LINK(this, SvxNumOptionsTabPage, PreviewInvalidateHdl_Impl));
aInvalidateTimer.SetTimeout(50);
m_aInvalidateTimer.SetInvokeHandler(
LINK(this, SvxNumOptionsTabPage, PreviewInvalidateHdl_Impl));
m_aInvalidateTimer.SetTimeout(50);
eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE));
m_eCoreUnit
= rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE));
// Fill ListBox with predefined / translated numbering types.
sal_uInt32 nCount = SvxNumberingTypeTable::Count();
@@ -1244,8 +1245,8 @@ SvxNumOptionsTabPage::~SvxNumOptionsTabPage()
{
m_xPreviewWIN.reset();
m_xBulColLB.reset();
pActNum.reset();
pSaveNum.reset();
m_pActNum.reset();
m_pSaveNum.reset();
if (m_pLevelHdlEvent)
{
Application::RemoveUserEvent(m_pLevelHdlEvent);
@@ -1277,34 +1278,34 @@ void SvxNumOptionsTabPage::ActivatePage(const SfxItemSet& rSet)
if(pExampleSet)
{
if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false))
bPreset = pPresetItem->GetValue();
m_bPreset = pPresetItem->GetValue();
if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false))
nTmpNumLvl = pLevelItem->GetValue();
}
if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false))
if (const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(m_nNumItemId, false))
{
pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) );
m_pSaveNum.reset(new SvxNumRule(pBulletItem->GetNumRule()));
}
bModified = (!pActNum->Get( 0 ) || bPreset);
if(*pActNum == *pSaveNum && nActNumLvl == nTmpNumLvl)
m_bModified = (!m_pActNum->Get(0) || m_bPreset);
if (*m_pActNum == *m_pSaveNum && m_nActNumLvl == nTmpNumLvl)
return;
nActNumLvl = nTmpNumLvl;
m_nActNumLvl = nTmpNumLvl;
sal_uInt16 nMask = 1;
m_xLevelLB->unselect_all();
if (nActNumLvl == SAL_MAX_UINT16)
m_xLevelLB->select(pActNum->GetLevelCount());
if(nActNumLvl != SAL_MAX_UINT16)
if (m_nActNumLvl == SAL_MAX_UINT16)
m_xLevelLB->select(m_pActNum->GetLevelCount());
if (m_nActNumLvl != SAL_MAX_UINT16)
{
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
m_xLevelLB->select(i);
nMask <<= 1 ;
}
}
*pActNum = *pSaveNum;
*m_pActNum = *m_pSaveNum;
InitControls();
}
@@ -1318,14 +1319,14 @@ DeactivateRC SvxNumOptionsTabPage::DeactivatePage(SfxItemSet * _pSet)
bool SvxNumOptionsTabPage::FillItemSet( SfxItemSet* rSet )
{
rSet->Put(SfxUInt16Item(SID_PARAM_CUR_NUM_LEVEL, nActNumLvl));
if(bModified && pActNum)
rSet->Put(SfxUInt16Item(SID_PARAM_CUR_NUM_LEVEL, m_nActNumLvl));
if (m_bModified && m_pActNum)
{
*pSaveNum = *pActNum;
rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId ));
*m_pSaveNum = *m_pActNum;
rSet->Put(SvxNumBulletItem(*m_pSaveNum, m_nNumItemId));
rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, false));
}
return bModified;
return m_bModified;
};
void SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet )
@@ -1335,25 +1336,25 @@ void SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet )
rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false);
if(!pBulletItem)
{
nNumItemId = rSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE);
pBulletItem = rSet->GetItemIfSet(nNumItemId, false);
m_nNumItemId = rSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE);
pBulletItem = rSet->GetItemIfSet(m_nNumItemId, false);
if( !pBulletItem )
{
pBulletItem = & rSet->Get( nNumItemId );
pBulletItem = &rSet->Get(m_nNumItemId);
}
}
DBG_ASSERT(pBulletItem, "no item found!");
pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) );
m_pSaveNum.reset(new SvxNumRule(pBulletItem->GetNumRule()));
// insert levels
if (!m_xLevelLB->n_children())
{
for(sal_uInt16 i = 1; i <= pSaveNum->GetLevelCount(); i++)
for (sal_uInt16 i = 1; i <= m_pSaveNum->GetLevelCount(); i++)
m_xLevelLB->append_text(OUString::number(i));
if(pSaveNum->GetLevelCount() > 1)
if (m_pSaveNum->GetLevelCount() > 1)
{
OUString sEntry = "1 - " + OUString::number( pSaveNum->GetLevelCount() );
OUString sEntry = "1 - " + OUString::number(m_pSaveNum->GetLevelCount());
m_xLevelLB->append_text(sEntry);
m_xLevelLB->select_text(sEntry);
}
@@ -1365,26 +1366,26 @@ void SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet )
sal_uInt16 nMask = 1;
m_xLevelLB->unselect_all();
if (nActNumLvl == SAL_MAX_UINT16)
if (m_nActNumLvl == SAL_MAX_UINT16)
{
m_xLevelLB->select( pSaveNum->GetLevelCount() );
m_xLevelLB->select(m_pSaveNum->GetLevelCount());
}
else
{
for(sal_uInt16 i = 0; i < pSaveNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pSaveNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
m_xLevelLB->select( i );
nMask <<= 1 ;
}
}
if(!pActNum)
pActNum.reset( new SvxNumRule(*pSaveNum) );
else if(*pSaveNum != *pActNum)
*pActNum = *pSaveNum;
m_aPreviewWIN.SetNumRule(pActNum.get());
m_xSameLevelCB->set_active(pActNum->IsContinuousNumbering());
if (!m_pActNum)
m_pActNum.reset(new SvxNumRule(*m_pSaveNum));
else if (*m_pSaveNum != *m_pActNum)
*m_pActNum = *m_pSaveNum;
m_aPreviewWIN.SetNumRule(m_pActNum.get());
m_xSameLevelCB->set_active(m_pActNum->IsContinuousNumbering());
const SfxUInt16Item* pHtmlModeItem =
rSet->GetItemIfSet( SID_HTML_MODE, false );
@@ -1396,16 +1397,16 @@ void SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet )
if ( pHtmlModeItem )
{
sal_uInt16 nHtmlMode = pHtmlModeItem->GetValue();
bHTMLMode = 0 != (nHtmlMode&HTMLMODE_ON);
m_bHTMLMode = 0 != (nHtmlMode & HTMLMODE_ON);
}
bool bCharFmt = pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE);
bool bCharFmt = m_pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE);
m_xCharFmtFT->set_visible(bCharFmt);
m_xCharFmtLB->set_visible(bCharFmt);
bool bContinuous = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
bool bContinuous = m_pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
bool bAllLevel = bContinuous && !bHTMLMode;
bool bAllLevel = bContinuous && !m_bHTMLMode;
m_xAllLevelFT->set_visible(bAllLevel);
m_xAllLevelNF->set_visible(bAllLevel);
m_xIsLegalCB->set_visible(bAllLevel);
@@ -1427,13 +1428,13 @@ void SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet )
}
}
//one must be enabled
if(!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_LINKED_BMP))
if (!m_pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_LINKED_BMP))
{
auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP|LINK_TOKEN));
if (nPos != -1)
m_xFmtLB->remove(nPos);
}
else if(!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP))
else if (!m_pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP))
{
auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP));
if (nPos != -1)
@@ -1442,7 +1443,7 @@ void SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet )
// MegaHack: because of a not-fixable 'design mistake/error' in Impress
// delete all kinds of numeric enumerations
if(pActNum->IsFeatureSupported(SvxNumRuleFlags::NO_NUMBERS))
if (m_pActNum->IsFeatureSupported(SvxNumRuleFlags::NO_NUMBERS))
{
sal_Int32 nFmtCount = m_xFmtLB->get_count();
for(sal_Int32 i = nFmtCount; i; i--)
@@ -1454,7 +1455,7 @@ void SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet )
}
InitControls();
bModified = false;
m_bModified = false;
const SvxLanguageItem* pLangItem = rSet->GetItemIfSet(SID_ATTR_CHAR_LANGUAGE, true);
if (!pLangItem)
pLangItem = rSet->GetItemIfSet(EE_CHAR_LANGUAGE, true);
@@ -1487,13 +1488,13 @@ void SvxNumOptionsTabPage::InitControls()
sal_uInt16 nLvl = SAL_MAX_UINT16;
sal_uInt16 nHighestLevel = 0;
bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR);
bool bBullRelSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE);
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
bool bBullColor = m_pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR);
bool bBullRelSize = m_pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE);
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
aNumFmtArr[i] = &pActNum->GetLevel(i);
aNumFmtArr[i] = &m_pActNum->GetLevel(i);
bShowBullet &= aNumFmtArr[i]->GetNumberingType() == SVX_NUM_CHAR_SPECIAL;
bShowBitmap &= (aNumFmtArr[i]->GetNumberingType()&(~LINK_TOKEN)) == SVX_NUM_BITMAP;
if(SAL_MAX_UINT16 == nLvl)
@@ -1558,8 +1559,8 @@ void SvxNumOptionsTabPage::InitControls()
if(bSameSize)
{
SetMetricValue(*m_xHeightMF, aFirstSize.Height(), eCoreUnit);
SetMetricValue(*m_xWidthMF, aFirstSize.Width(), eCoreUnit);
SetMetricValue(*m_xHeightMF, aFirstSize.Height(), m_eCoreUnit);
SetMetricValue(*m_xWidthMF, aFirstSize.Width(), m_eCoreUnit);
}
else
{
@@ -1605,7 +1606,7 @@ void SvxNumOptionsTabPage::InitControls()
m_xBulColLB->SetNoSelection();
}
m_xStartED->set_value(1); // If this isn't set then changing the bullet type to a numbered type doesn't reset the start level
switch(nBullet)
switch (m_nBullet)
{
case NumberType::SHOW_NUMBERING:
if(bSameStart)
@@ -1642,16 +1643,16 @@ void SvxNumOptionsTabPage::InitControls()
else
m_xCharFmtLB->set_active(-1);
m_aPreviewWIN.SetLevel(nActNumLvl);
m_aPreviewWIN.SetLevel(m_nActNumLvl);
m_aPreviewWIN.Invalidate();
}
// 0 - Number; 1 - Bullet; 2 - Bitmap
void SvxNumOptionsTabPage::SwitchNumberType( NumberType nType )
{
if(nBullet == nType)
if (m_nBullet == nType)
return;
nBullet = nType;
m_nBullet = nType;
bool bBullet = (nType == NumberType::SHOW_BULLET);
bool bBitmap = (nType == NumberType::SHOW_BITMAP);
bool bEnableBitmap = (nType == NumberType::SHOW_BITMAP);
@@ -1662,14 +1663,14 @@ void SvxNumOptionsTabPage::SwitchNumberType( NumberType nType )
m_xSuffixFT->set_visible(bNumeric);
m_xSuffixED->set_visible(bNumeric);
bool bCharFmt = pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE);
bool bCharFmt = m_pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE);
m_xCharFmtFT->set_visible(!bBitmap && bCharFmt);
m_xCharFmtLB->set_visible(!bBitmap && bCharFmt);
// this is rather misusage, as there is no own flag
// for complete numeration
bool bAllLevelFeature = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
bool bAllLevel = bNumeric && bAllLevelFeature && !bHTMLMode;
bool bAllLevelFeature = m_pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
bool bAllLevel = bNumeric && bAllLevelFeature && !m_bHTMLMode;
m_xAllLevelFT->set_visible(bAllLevel);
m_xAllLevelNF->set_visible(bAllLevel);
m_xIsLegalCB->set_visible(bAllLevel);
@@ -1679,15 +1680,17 @@ void SvxNumOptionsTabPage::SwitchNumberType( NumberType nType )
m_xBulletFT->set_visible(bBullet);
m_xBulletPB->set_visible(bBullet);
bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR);
bool bBullColor = m_pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR);
m_xBulColorFT->set_visible(!bBitmap && bBullColor);
m_xBulColLB->set_visible(!bBitmap && bBullColor);
bool bBullResSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE);
bool bBullResSize = m_pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE);
m_xBulRelSizeFT->set_visible(!bBitmap && bBullResSize);
m_xBulRelSizeMF->set_visible(!bBitmap && bBullResSize);
m_xBitmapFT->set_visible(bBitmap);
m_xBitmapMB->set_visible(bBitmap);
if (bBitmap)
CreateGalleryMenu();
m_xWidthFT->set_visible(bBitmap);
m_xWidthMF->set_visible(bBitmap);
@@ -1724,34 +1727,35 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, LevelHdl, void*, void)
{
m_pLevelHdlEvent = nullptr;
sal_uInt16 nSaveNumLvl = nActNumLvl;
nActNumLvl = 0;
sal_uInt16 nSaveNumLvl = m_nActNumLvl;
m_nActNumLvl = 0;
std::vector<int> aSelectedRows = m_xLevelLB->get_selected_rows();
if (std::find(aSelectedRows.begin(), aSelectedRows.end(), pActNum->GetLevelCount()) != aSelectedRows.end() &&
(aSelectedRows.size() == 1 || nSaveNumLvl != 0xffff))
if (std::find(aSelectedRows.begin(), aSelectedRows.end(), m_pActNum->GetLevelCount())
!= aSelectedRows.end()
&& (aSelectedRows.size() == 1 || nSaveNumLvl != 0xffff))
{
nActNumLvl = 0xFFFF;
for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ )
m_nActNumLvl = 0xFFFF;
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
m_xLevelLB->unselect(i);
}
else if (!aSelectedRows.empty())
{
sal_uInt16 nMask = 1;
for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ )
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if (std::find(aSelectedRows.begin(), aSelectedRows.end(), i) != aSelectedRows.end())
nActNumLvl |= nMask;
m_nActNumLvl |= nMask;
nMask <<= 1;
}
m_xLevelLB->unselect(pActNum->GetLevelCount());
m_xLevelLB->unselect(m_pActNum->GetLevelCount());
}
else
{
nActNumLvl = nSaveNumLvl;
m_nActNumLvl = nSaveNumLvl;
sal_uInt16 nMask = 1;
for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ )
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
m_xLevelLB->select(i);
break;
@@ -1770,15 +1774,15 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, PreviewInvalidateHdl_Impl, Timer *, void)
IMPL_LINK(SvxNumOptionsTabPage, AllLevelHdl_Impl, weld::SpinButton&, rBox, void)
{
sal_uInt16 nMask = 1;
for(sal_uInt16 e = 0; e < pActNum->GetLevelCount(); e++)
for (sal_uInt16 e = 0; e < m_pActNum->GetLevelCount(); e++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(e));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(e));
aNumFmt.SetIncludeUpperLevels(static_cast<sal_uInt8>(std::min(rBox.get_value(), sal_Int64(e + 1))) );
// Set the same prefix/suffix to generate list format with changed IncludedUpperLevels
aNumFmt.SetListFormat(aNumFmt.GetPrefix(), aNumFmt.GetSuffix(), e);
pActNum->SetLevel(e, aNumFmt);
m_pActNum->SetLevel(e, aNumFmt);
}
nMask <<= 1;
}
@@ -1788,13 +1792,13 @@ IMPL_LINK(SvxNumOptionsTabPage, AllLevelHdl_Impl, weld::SpinButton&, rBox, void)
IMPL_LINK(SvxNumOptionsTabPage, IsLegalHdl_Impl, weld::Toggleable&, rBox, void)
{
bool bSet = rBox.get_active();
for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if (nActNumLvl & (sal_uInt16(1) << i))
if (m_nActNumLvl & (sal_uInt16(1) << i))
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
aNumFmt.SetIsLegal(bSet);
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
}
}
SetModified();
@@ -1806,11 +1810,11 @@ IMPL_LINK(SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox,
bool bShowOrient = false;
bool bBmp = false;
sal_uInt16 nMask = 1;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
// PAGEDESC does not exist
SvxNumType nNumType = static_cast<SvxNumType>(rBox.get_active_id().toUInt32());
aNumFmt.SetNumberingType(nNumType);
@@ -1822,7 +1826,7 @@ IMPL_LINK(SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox,
aNumFmt.SetListFormat(u""_ustr, u""_ustr, i);
if(!bBmp)
aNumFmt.SetGraphic(u""_ustr);
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
SwitchNumberType(NumberType::SHOW_BITMAP);
bShowOrient = true;
}
@@ -1831,13 +1835,13 @@ IMPL_LINK(SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox,
aNumFmt.SetIncludeUpperLevels( 1 );
aNumFmt.SetListFormat(u""_ustr, u""_ustr, i);
if( !aNumFmt.GetBulletFont() )
aNumFmt.SetBulletFont(&aActBulletFont);
aNumFmt.SetBulletFont(&m_aActBulletFont);
if( !aNumFmt.GetBulletChar() )
aNumFmt.SetBulletChar( SVX_DEF_BULLET );
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
SwitchNumberType(NumberType::SHOW_BULLET);
// allocation of the drawing pattern is automatic
if(bAutomaticCharStyles)
if (m_bAutomaticCharStyles)
{
sSelectStyle = m_sBulletCharFormatName;
}
@@ -1847,11 +1851,11 @@ IMPL_LINK(SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox,
aNumFmt.SetListFormat(m_xPrefixED->get_text(), m_xSuffixED->get_text(), i);
SwitchNumberType(NumberType::SHOW_NUMBERING);
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
CheckForStartValue_Impl(nNumberingType);
// allocation of the drawing pattern is automatic
if(bAutomaticCharStyles)
if (m_bAutomaticCharStyles)
{
sSelectStyle = m_sNumCharFmtName;
}
@@ -1859,7 +1863,7 @@ IMPL_LINK(SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox,
}
nMask <<= 1;
}
bool bAllLevelFeature = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
bool bAllLevelFeature = m_pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
if(bShowOrient && bAllLevelFeature)
{
m_xOrientFT->show();
@@ -1875,7 +1879,7 @@ IMPL_LINK(SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox,
{
m_xCharFmtLB->set_active_text(sSelectStyle);
CharFmtHdl_Impl(*m_xCharFmtLB);
bAutomaticCharStyles = true;
m_bAutomaticCharStyles = true;
}
}
@@ -1896,18 +1900,18 @@ IMPL_LINK(SvxNumOptionsTabPage, OrientHdl_Impl, weld::ComboBox&, rBox, void)
nPos ++; // no VERT_NONE
sal_uInt16 nMask = 1;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
if(SVX_NUM_BITMAP == (aNumFmt.GetNumberingType()&(~LINK_TOKEN)))
{
const SvxBrushItem* pBrushItem = aNumFmt.GetBrush();
const Size& rSize = aNumFmt.GetGraphicSize();
sal_Int16 eOrient = static_cast<sal_Int16>(nPos);
aNumFmt.SetGraphicBrush( pBrushItem, &rSize, &eOrient );
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
}
}
nMask <<= 1;
@@ -1918,11 +1922,11 @@ IMPL_LINK(SvxNumOptionsTabPage, OrientHdl_Impl, weld::ComboBox&, rBox, void)
IMPL_LINK(SvxNumOptionsTabPage, SameLevelHdl_Impl, weld::Toggleable&, rBox, void)
{
bool bSet = rBox.get_active();
pActNum->SetContinuousNumbering(bSet);
m_pActNum->SetContinuousNumbering(bSet);
bool bRepaint = false;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
if(aNumFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE)
{
bRepaint = true;
@@ -1938,13 +1942,13 @@ IMPL_LINK(SvxNumOptionsTabPage, BulColorHdl_Impl, ColorListBox&, rColorBox, void
Color nSetColor = rColorBox.GetSelectEntryColor();
sal_uInt16 nMask = 1;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
aNumFmt.SetBulletColor(nSetColor);
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
}
nMask <<= 1;
}
@@ -1956,13 +1960,13 @@ IMPL_LINK(SvxNumOptionsTabPage, BulRelSizeHdl_Impl, weld::MetricSpinButton&, rFi
sal_uInt16 nRelSize = o3tl::sanitizing_cast<sal_uInt16>(rField.get_value(FieldUnit::PERCENT));
sal_uInt16 nMask = 1;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
aNumFmt.SetBulletRelSize(nRelSize);
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
}
nMask <<= 1;
}
@@ -1980,9 +1984,9 @@ IMPL_LINK(SvxNumOptionsTabPage, GraphicHdl_Impl, const OUString&, rIdent, void)
if (rIdent.startsWith("gallery", &sNumber))
{
auto idx = o3tl::toUInt32(sNumber);
if (idx < aGrfNames.size())
if (idx < m_aGrfNames.size())
{
aGrfName = aGrfNames[idx];
aGrfName = m_aGrfNames[idx];
Graphic aGraphic;
if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, idx, &aGraphic))
{
@@ -2011,14 +2015,14 @@ IMPL_LINK(SvxNumOptionsTabPage, GraphicHdl_Impl, const OUString&, rIdent, void)
if(!bSucc)
return;
aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(eCoreUnit));
aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(m_eCoreUnit));
sal_uInt16 nMask = 1;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
aNumFmt.SetCharFormatName(m_sNumCharFmtName);
aNumFmt.SetGraphic(aGrfName);
@@ -2027,9 +2031,9 @@ IMPL_LINK(SvxNumOptionsTabPage, GraphicHdl_Impl, const OUString&, rIdent, void)
// initiate asynchronous loading
sal_Int16 eOrient = aNumFmt.GetVertOrient();
aNumFmt.SetGraphicBrush( pBrushItem, &aSize, &eOrient );
aInitSize[i] = aNumFmt.GetGraphicSize();
m_aInitSize[i] = aNumFmt.GetGraphicSize();
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
}
nMask <<= 1;
}
@@ -2038,16 +2042,16 @@ IMPL_LINK(SvxNumOptionsTabPage, GraphicHdl_Impl, const OUString&, rIdent, void)
m_xHeightFT->set_sensitive(true);
m_xWidthMF->set_sensitive(true);
m_xHeightMF->set_sensitive(true);
SetMetricValue(*m_xWidthMF, aSize.Width(), eCoreUnit);
SetMetricValue(*m_xHeightMF, aSize.Height(), eCoreUnit);
SetMetricValue(*m_xWidthMF, aSize.Width(), m_eCoreUnit);
SetMetricValue(*m_xHeightMF, aSize.Height(), m_eCoreUnit);
m_xOrientFT->set_sensitive(true);
m_xOrientLB->set_sensitive(true);
SetModified();
//needed due to asynchronous loading of graphics in the SvxBrushItem
aInvalidateTimer.Start();
m_aInvalidateTimer.Start();
}
IMPL_LINK_NOARG(SvxNumOptionsTabPage, PopupActivateHdl_Impl, weld::Toggleable&, void)
void SvxNumOptionsTabPage::CreateGalleryMenu()
{
if (m_xGalleryMenu)
return;
@@ -2055,7 +2059,7 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, PopupActivateHdl_Impl, weld::Toggleable&,
m_xGalleryMenu = m_xBuilder->weld_menu(u"gallerysubmenu"_ustr);
weld::WaitObject aWait(GetFrameWeld());
if (!GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, aGrfNames))
if (!GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, m_aGrfNames))
return;
GalleryExplorer::BeginLocking(GALLERY_THEME_BULLETS);
@@ -2064,7 +2068,7 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, PopupActivateHdl_Impl, weld::Toggleable&,
OUString sGrfName;
ScopedVclPtrInstance< VirtualDevice > pVD;
size_t i = 0;
for (const auto & grfName : aGrfNames)
for (const auto& grfName : m_aGrfNames)
{
sGrfName = grfName;
OUString sItemId = "gallery" + OUString::number(i);
@@ -2110,11 +2114,11 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, BulletHdl_Impl, weld::Button&, void)
bool bSameBullet = true;
sal_UCS4 cBullet = 0;
bool bFirst = true;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
const SvxNumberFormat& rCurFmt = pActNum->GetLevel(i);
const SvxNumberFormat& rCurFmt = m_pActNum->GetLevel(i);
if(bFirst)
{
cBullet = rCurFmt.GetBulletChar();
@@ -2135,24 +2139,24 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, BulletHdl_Impl, weld::Button&, void)
if (pFmtFont)
aMap.SetCharFont(*pFmtFont);
else
aMap.SetCharFont(aActBulletFont);
aMap.SetCharFont(m_aActBulletFont);
if (bSameBullet)
aMap.SetChar(cBullet);
if (aMap.run() != RET_OK)
return;
// change Font Numrules
aActBulletFont = aMap.GetCharFont();
m_aActBulletFont = aMap.GetCharFont();
sal_uInt16 _nMask = 1;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & _nMask)
if (m_nActNumLvl & _nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
aNumFmt.SetBulletFont(&aActBulletFont);
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
aNumFmt.SetBulletFont(&m_aActBulletFont);
aNumFmt.SetBulletChar(aMap.GetChar());
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
}
_nMask <<= 1;
}
@@ -2163,54 +2167,58 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, BulletHdl_Impl, weld::Button&, void)
IMPL_LINK( SvxNumOptionsTabPage, SizeHdl_Impl, weld::MetricSpinButton&, rField, void)
{
bool bWidth = &rField == m_xWidthMF.get();
bLastWidthModified = bWidth;
m_bLastWidthModified = bWidth;
bool bRatio = m_xRatioCB->get_active();
tools::Long nWidthVal = static_cast<tools::Long>(m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::MM_100TH)));
tools::Long nHeightVal = static_cast<tools::Long>(m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::MM_100TH)));
nWidthVal = OutputDevice::LogicToLogic( nWidthVal ,
MapUnit::Map100thMM, eCoreUnit );
nHeightVal = OutputDevice::LogicToLogic( nHeightVal,
MapUnit::Map100thMM, eCoreUnit);
nWidthVal = OutputDevice::LogicToLogic(nWidthVal, MapUnit::Map100thMM, m_eCoreUnit);
nHeightVal = OutputDevice::LogicToLogic(nHeightVal, MapUnit::Map100thMM, m_eCoreUnit);
double fSizeRatio;
bool bRepaint = false;
sal_uInt16 nMask = 1;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
if(SVX_NUM_BITMAP == (aNumFmt.GetNumberingType()&(~LINK_TOKEN)))
{
Size aSize(aNumFmt.GetGraphicSize() );
Size aSaveSize(aSize);
if (aInitSize[i].Height())
fSizeRatio = static_cast<double>(aInitSize[i].Width()) / static_cast<double>(aInitSize[i].Height());
if (m_aInitSize[i].Height())
fSizeRatio = static_cast<double>(m_aInitSize[i].Width())
/ static_cast<double>(m_aInitSize[i].Height());
else
fSizeRatio = double(1);
if(bWidth)
{
tools::Long nDelta = nWidthVal - aInitSize[i].Width();
tools::Long nDelta = nWidthVal - m_aInitSize[i].Width();
aSize.setWidth( nWidthVal );
if (bRatio)
{
aSize.setHeight( aInitSize[i].Height() + static_cast<tools::Long>(static_cast<double>(nDelta) / fSizeRatio) );
m_xHeightMF->set_value(m_xHeightMF->normalize(
OutputDevice::LogicToLogic( aSize.Height(), eCoreUnit, MapUnit::Map100thMM )),
aSize.setHeight(
m_aInitSize[i].Height()
+ static_cast<tools::Long>(static_cast<double>(nDelta) / fSizeRatio));
m_xHeightMF->set_value(
m_xHeightMF->normalize(OutputDevice::LogicToLogic(
aSize.Height(), m_eCoreUnit, MapUnit::Map100thMM)),
FieldUnit::MM_100TH);
}
}
else
{
tools::Long nDelta = nHeightVal - aInitSize[i].Height();
tools::Long nDelta = nHeightVal - m_aInitSize[i].Height();
aSize.setHeight( nHeightVal );
if (bRatio)
{
aSize.setWidth( aInitSize[i].Width() + static_cast<tools::Long>(static_cast<double>(nDelta) * fSizeRatio) );
m_xWidthMF->set_value(m_xWidthMF->normalize(
OutputDevice::LogicToLogic( aSize.Width(), eCoreUnit, MapUnit::Map100thMM )),
aSize.setWidth(
m_aInitSize[i].Width()
+ static_cast<tools::Long>(static_cast<double>(nDelta) * fSizeRatio));
m_xWidthMF->set_value(m_xWidthMF->normalize(OutputDevice::LogicToLogic(
aSize.Width(), m_eCoreUnit, MapUnit::Map100thMM)),
FieldUnit::MM_100TH);
}
}
@@ -2219,7 +2227,7 @@ IMPL_LINK( SvxNumOptionsTabPage, SizeHdl_Impl, weld::MetricSpinButton&, rField,
if(aSize != aSaveSize)
bRepaint = true;
aNumFmt.SetGraphicBrush( pBrushItem, &aSize, &eOrient );
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
}
}
nMask <<= 1;
@@ -2232,7 +2240,7 @@ IMPL_LINK(SvxNumOptionsTabPage, RatioHdl_Impl, weld::Toggleable&, rBox, void)
m_xCbxScaleImg->set_from_icon_name(m_xRatioCB->get_active() ? RID_SVXBMP_LOCKED : RID_SVXBMP_UNLOCKED);
if (rBox.get_active())
{
if (bLastWidthModified)
if (m_bLastWidthModified)
SizeHdl_Impl(*m_xWidthMF);
else
SizeHdl_Impl(*m_xHeightMF);
@@ -2241,15 +2249,15 @@ IMPL_LINK(SvxNumOptionsTabPage, RatioHdl_Impl, weld::Toggleable&, rBox, void)
IMPL_LINK_NOARG(SvxNumOptionsTabPage, CharFmtHdl_Impl, weld::ComboBox&, void)
{
bAutomaticCharStyles = false;
m_bAutomaticCharStyles = false;
sal_Int32 nEntryPos = m_xCharFmtLB->get_active();
OUString sEntry = m_xCharFmtLB->get_active_text();
sal_uInt16 nMask = 1;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
if( 0 == nEntryPos )
aNumFmt.SetCharFormatName(u""_ustr);
else
@@ -2257,7 +2265,7 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, CharFmtHdl_Impl, weld::ComboBox&, void)
if(SVX_NUM_BITMAP != (aNumFmt.GetNumberingType()&(~LINK_TOKEN)))
aNumFmt.SetCharFormatName(sEntry);
}
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
}
nMask <<= 1;
}
@@ -2279,16 +2287,16 @@ void SvxNumOptionsTabPage::EditModifyHdl_Impl(const weld::TextWidget* pEdit)
bool bPrefixSuffix = (pEdit == m_xPrefixED.get())|| (pEdit == m_xSuffixED.get());
bool bStart = pEdit == m_xStartED.get();
sal_uInt16 nMask = 1;
for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
for (sal_uInt16 i = 0; i < m_pActNum->GetLevelCount(); i++)
{
if(nActNumLvl & nMask)
if (m_nActNumLvl & nMask)
{
SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
SvxNumberFormat aNumFmt(m_pActNum->GetLevel(i));
if (bPrefixSuffix)
aNumFmt.SetListFormat(m_xPrefixED->get_text(), m_xSuffixED->get_text(), i);
else if(bStart)
aNumFmt.SetStart(m_xStartED->get_value());
pActNum->SetLevel(i, aNumFmt);
m_pActNum->SetLevel(i, aNumFmt);
}
nMask <<= 1;
}
@@ -3150,10 +3158,10 @@ void SvxNumPositionTabPage::SetModified()
void SvxNumOptionsTabPage::SetModified(bool bRepaint)
{
bModified = true;
m_bModified = true;
if (bRepaint)
{
m_aPreviewWIN.SetLevel(nActNumLvl);
m_aPreviewWIN.SetLevel(m_nActNumLvl);
m_aPreviewWIN.Invalidate();
}
}
+9 -1
View File
@@ -1299,6 +1299,7 @@ SvxParaAlignTabPage::SvxParaAlignTabPage(weld::Container* pPage, weld::DialogCon
, m_xLabelLetterSpacing(m_xBuilder->weld_label(u"labelLetterSpacing"_ustr))
, m_xLetterSpacingMinimum(m_xBuilder->weld_metric_spin_button(u"spin_LETTER_SPACING_MIN"_ustr, FieldUnit::PERCENT))
, m_xLetterSpacingMaximum(m_xBuilder->weld_metric_spin_button(u"spin_LETTER_SPACING_MAX"_ustr, FieldUnit::PERCENT))
, m_xCompoundBased(m_xBuilder->weld_check_button(u"checkCompoundBased"_ustr))
, m_xLabelGlyphScaling(m_xBuilder->weld_label(u"labelGlyphScaling"_ustr))
, m_xGlyphScalingMinimum(m_xBuilder->weld_metric_spin_button(u"spin_GLYPH_SCALING_MIN"_ustr, FieldUnit::PERCENT))
, m_xGlyphScalingMaximum(m_xBuilder->weld_metric_spin_button(u"spin_GLYPH_SCALING_MAX"_ustr, FieldUnit::PERCENT))
@@ -1409,6 +1410,7 @@ bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* rOutSet )
m_xParagraphComposer->get_state_changed_from_saved() ||
m_xLetterSpacingMinimum->get_value_changed_from_saved() ||
m_xLetterSpacingMaximum->get_value_changed_from_saved() ||
m_xCompoundBased->get_state_changed_from_saved() ||
m_xGlyphScalingMinimum->get_value_changed_from_saved() ||
m_xGlyphScalingMaximum->get_value_changed_from_saved();
}
@@ -1436,6 +1438,7 @@ bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* rOutSet )
aAdj.SetParagraphComposer( m_xParagraphComposer->get_active() );
aAdj.SetPropLetterSpacingMinimum( m_xLetterSpacingMinimum->get_value(FieldUnit::PERCENT) );
aAdj.SetPropLetterSpacingMaximum( m_xLetterSpacingMaximum->get_value(FieldUnit::PERCENT) );
aAdj.SetCompoundBased( m_xCompoundBased->get_active() );
aAdj.SetPropScaleWidthMinimum( m_xGlyphScalingMinimum->get_value(FieldUnit::PERCENT) );
aAdj.SetPropScaleWidthMaximum( m_xGlyphScalingMaximum->get_value(FieldUnit::PERCENT) );
rOutSet->Put( aAdj );
@@ -1543,6 +1546,8 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
m_xLetterSpacingMinimum->set_sensitive(true);
m_xLetterSpacingMinimum->set_value(rAdj.GetPropLetterSpacingMinimum(), FieldUnit::PERCENT);
m_xLetterSpacingMaximum->set_value(rAdj.GetPropLetterSpacingMaximum(), FieldUnit::PERCENT);
m_xCompoundBased->set_sensitive(true);
m_xCompoundBased->set_active(rAdj.GetCompoundBased());
// TODO add GlyphScaling (CharScaleWidth)
m_xGlyphScalingMaximum->set_sensitive(true);
m_xGlyphScalingMinimum->set_sensitive(true);
@@ -1559,10 +1564,10 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
m_xWordSpacingMinimum->set_sensitive(false);
m_xWordSpacingMaximum->set_sensitive(false);
m_xParagraphComposer->set_sensitive(false);
m_xParagraphComposer->set_sensitive(false);
m_xLabelLetterSpacing->set_sensitive(false);
m_xLetterSpacingMinimum->set_sensitive(false);
m_xLetterSpacingMaximum->set_sensitive(false);
m_xCompoundBased->set_sensitive(false);
m_xLabelGlyphScaling->set_sensitive(false);
m_xGlyphScalingMinimum->set_sensitive(false);
m_xGlyphScalingMaximum->set_sensitive(false);
@@ -1664,6 +1669,7 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
m_xParagraphComposer->save_state();
m_xLetterSpacingMinimum->save_value();
m_xLetterSpacingMaximum->save_value();
m_xCompoundBased->save_state();
m_xGlyphScalingMinimum->save_value();
m_xGlyphScalingMaximum->save_value();
@@ -1690,6 +1696,7 @@ void SvxParaAlignTabPage::ChangesApplied()
m_xParagraphComposer->save_state();
m_xLetterSpacingMinimum->save_value();
m_xLetterSpacingMaximum->save_value();
m_xCompoundBased->save_state();
m_xGlyphScalingMinimum->save_value();
m_xGlyphScalingMaximum->save_value();
}
@@ -1711,6 +1718,7 @@ IMPL_LINK_NOARG(SvxParaAlignTabPage, AlignHdl_Impl, weld::Toggleable&, void)
// TODO visualize CharKerning with percentage
m_xLetterSpacingMinimum->set_sensitive(bJustify);
m_xLetterSpacingMaximum->set_sensitive(bJustify);
m_xCompoundBased->set_sensitive(bJustify);
m_xLabelGlyphScaling->set_sensitive(bJustify);
// TODO visualize CharScaleWidth with percentage
m_xGlyphScalingMinimum->set_sensitive(bJustify);
+7 -11
View File
@@ -185,7 +185,7 @@ void SvxColorTabPage::ActivatePage( const SfxItemSet& )
if (nSelectedIndex < 0)
return;
ActivatePaletteColorHdl(m_aColorIconView.getColor(nSelectedIndex));
ActivatePaletteColorHdl(nSelectedIndex);
}
DeactivateRC SvxColorTabPage::DeactivatePage( SfxItemSet* _pSet )
@@ -388,7 +388,7 @@ IMPL_LINK_NOARG(SvxColorTabPage, ClickDeleteHdl_Impl, weld::Button&, void)
if (m_aColorIconView.getItemCount() > 0)
{
m_aColorIconView.select(0);
ActivatePaletteColorHdl(m_aColorIconView.getColor(0));
ActivatePaletteColorHdl(0);
}
else
{
@@ -481,20 +481,16 @@ void SvxColorTabPage::UpdateToSelectedColor(const NamedColor& rNamedColor)
ChangeColor(rNamedColor, false);
}
IMPL_LINK(SvxColorTabPage, ActivatePaletteColorHdl, const Color&, rColor, void)
IMPL_LINK(SvxColorTabPage, ActivatePaletteColorHdl, int, nIndex, void)
{
const int nPos = m_aColorIconView.get_selected_index();
if (nPos < 0 || m_aColorIconView.getColor(nPos) != rColor)
return;
NamedColor aNamedColor;
aNamedColor.m_aColor = rColor;
aNamedColor.m_aColor = m_aColorIconView.getColor(nIndex);
if (maPaletteManager.IsThemePaletteSelected())
{
sal_uInt16 nThemeIndex;
sal_uInt16 nEffectIndex;
if (PaletteManager::GetThemeAndEffectIndex(nPos, nThemeIndex, nEffectIndex))
if (PaletteManager::GetThemeAndEffectIndex(nIndex, nThemeIndex, nEffectIndex))
{
aNamedColor.m_nThemeIndex = nThemeIndex;
maPaletteManager.GetLumModOff(nThemeIndex, nEffectIndex, aNamedColor.m_nLumMod, aNamedColor.m_nLumOff);
@@ -516,10 +512,10 @@ IMPL_LINK(SvxColorTabPage, ActivatePaletteColorHdl, const Color&, rColor, void)
}
}
IMPL_LINK(SvxColorTabPage, ActivateRecentColorHdl, const Color&, rColor, void)
IMPL_LINK(SvxColorTabPage, ActivateRecentColorHdl, int, nIndex, void)
{
NamedColor aNamedColor;
aNamedColor.m_aColor = rColor;
aNamedColor.m_aColor = m_aRecentIconView.getColor(nIndex);
UpdateToSelectedColor(aNamedColor);
+6
View File
@@ -167,7 +167,10 @@
<property name="model">coloriconviewmodel</property>
<property name="columns">12</property>
<property name="pixbuf-column">0</property>
<property name="row-spacing">0</property>
<property name="column-spacing">0</property>
<property name="tooltip-column">2</property>
<property name="item-padding">2</property>
<property name="activate-on-single-click">True</property>
</object>
</child>
@@ -214,7 +217,10 @@
<property name="model">recentcoloriconviewmodel</property>
<property name="columns">12</property>
<property name="pixbuf-column">0</property>
<property name="row-spacing">0</property>
<property name="column-spacing">0</property>
<property name="tooltip-column">2</property>
<property name="item-padding">2</property>
<property name="activate-on-single-click">True</property>
</object>
<packing>
+3 -3
View File
@@ -164,7 +164,7 @@
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes" context="numberingoptionspage|label4">Number:</property>
<property name="label" translatable="yes" context="numberingoptionspage|label4">Type:</property>
<property name="use-underline">True</property>
<property name="mnemonic-widget">numfmtlb</property>
<property name="xalign">0</property>
@@ -180,7 +180,7 @@
<property name="can-focus">False</property>
<child internal-child="accessible">
<object class="AtkObject" id="numfmtlb-atkobject">
<property name="AtkObject::accessible-description" translatable="yes" context="numberingoptionspage|extended_tip|numfmtlb">Select a numbering scheme for the selected levels.</property>
<property name="AtkObject::accessible-description" translatable="yes" context="numberingoptionspage|extended_tip|numfmtlb">Select a numbering scheme or a bullet for the selected levels.</property>
</object>
</child>
<style>
@@ -754,7 +754,7 @@
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes" context="numberingoptionspage|label2">Numbering</property>
<property name="label" translatable="yes" context="numberingoptionspage|label2">List Format</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
+3
View File
@@ -210,7 +210,10 @@
<property name="model">tableiconview_model</property>
<property name="columns">12</property>
<property name="pixbuf-column">0</property>
<property name="row-spacing">0</property>
<property name="column-spacing">0</property>
<property name="tooltip-column">2</property>
<property name="item-padding">2</property>
<property name="activate-on-single-click">True</property>
</object>
</child>
+20
View File
@@ -740,6 +740,26 @@
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="checkCompoundBased">
<property name="label" translatable="yes" context="paralignpage|checkCompoundBased">Split compound words</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="use-underline">True</property>
<property name="inconsistent">True</property>
<property name="draw-indicator">True</property>
<child internal-child="accessible">
<object class="AtkObject" id="checkCompoundBased-atkobject">
<property name="AtkObject::accessible-description" translatable="yes" context="textflowpage|extended_tip|checkCompoundBased">Select this check box, if you want to prefer compound word splitting during justification.</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">4</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="labelGlyphScaling">
<property name="visible">True</property>
@@ -23,6 +23,7 @@ $(eval $(call gb_CppunitTest_use_libraries,dbaccess_firebird_test, \
cppu \
cppuhelper \
dbaxml \
dbtools \
firebird_sdbc \
sal \
subsequenttest \
@@ -0,0 +1,63 @@
# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/.
#
from uitest.framework import UITestCase
from uitest.uihelper.common import get_url_for_data_file, select_pos
from libreoffice.uno.propertyvalue import mkPropertyValues
# Bug 173673 - Tablefilter: Resetting impossible when "Apply Filter" is unchecked
class tdf173673(UITestCase):
def test_tdf173673(self):
with self.ui_test.load_file(get_url_for_data_file("tdf75509.odb")) as document:
xConnection = document.DataSource.getConnection("", "")
xStatement = xConnection.createStatement()
xStatement.executeUpdate('INSERT INTO "Table1" ("FrenchField", "EnglishField") VALUES (1, 1)')
xStatement.executeUpdate('INSERT INTO "Table1" ("FrenchField", "EnglishField") VALUES (2, 2)')
xConnection.close()
self.xUITest.executeCommand(".uno:DBViewTables")
xToolkit = self.xContext.ServiceManager.createInstance('com.sun.star.awt.Toolkit')
xToolkit.waitUntilAllIdlesDispatched()
self.xUITest.executeCommand(".uno:SelectAll")
with self.ui_test.open_subcomponent_through_command(".uno:DBTableOpen") as xTableFrame:
xTableWindow = self.xUITest.getWindow(xTableFrame.getContainerWindow())
xGrid = xTableWindow.getChild("DBGrid")
xForm = xTableFrame.getController().CurrentControl.getModel().getParent()
self.assertEqual(2, xForm.RowCount)
# AutoFilter on the first row's FrenchField cell (value 1)
xGrid.executeAction("FOCUS", tuple())
xGrid.executeAction("TYPE", mkPropertyValues({"KEYCODE": "TAB"}))
self.xUITest.executeCommandForProvider(".uno:AutoFilter", xTableFrame)
xToolkit.waitUntilAllIdlesDispatched()
self.assertNotEqual("", xForm.Filter)
self.assertTrue(xForm.ApplyFilter)
self.assertEqual(1, xForm.RowCount)
# Uncheck "Apply Filter": the filter is kept, but no longer applied
self.xUITest.executeCommandForProvider(".uno:FormFiltered", xTableFrame)
xToolkit.waitUntilAllIdlesDispatched()
self.assertNotEqual("", xForm.Filter)
self.assertFalse(xForm.ApplyFilter)
self.assertEqual(2, xForm.RowCount)
# Clear the condition in the Standard Filter dialog
with self.ui_test.execute_blocking_action(
self.xUITest.executeCommandForProvider,
args=(".uno:FilterCrit", xTableFrame)) as xDialog:
xDialog.getChild("field1").executeAction("SELECT", mkPropertyValues({"TEXT": "- none -"}))
xToolkit.waitUntilAllIdlesDispatched()
# Check that the old filter is removed
self.assertEqual("", xForm.Filter)
self.assertEqual(2, xForm.RowCount)
# vim: set shiftwidth=4 softtabstop=4 expandtab:
+187
View File
@@ -9,7 +9,13 @@
#include "dbtest_base.cxx"
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/sdb/SQLFilterOperator.hpp>
#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
#include <com/sun/star/sdbc/XColumnLocate.hpp>
#include <com/sun/star/sdbc/XConnection.hpp>
#include <com/sun/star/sdbc/XParameters.hpp>
@@ -17,6 +23,10 @@
#include <com/sun/star/sdbc/XResultSet.hpp>
#include <com/sun/star/sdbc/XRow.hpp>
#include <com/sun/star/sdbc/XStatement.hpp>
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
#include <com/sun/star/util/XRefreshable.hpp>
#include <connectivity/predicateinput.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::sdb;
@@ -31,12 +41,18 @@ public:
void testIntegerDatabase();
void testTdf132924();
void testTdf153057();
void testTdf153057_RangeFilter();
void testTdf153057_FractionalFilter();
void testTdf173589_TableStandardFilter();
CPPUNIT_TEST_SUITE(FirebirdTest);
CPPUNIT_TEST(testEmptyDBConnection);
CPPUNIT_TEST(testIntegerDatabase);
CPPUNIT_TEST(testTdf132924);
CPPUNIT_TEST(testTdf153057);
CPPUNIT_TEST(testTdf153057_RangeFilter);
CPPUNIT_TEST(testTdf153057_FractionalFilter);
CPPUNIT_TEST(testTdf173589_TableStandardFilter);
CPPUNIT_TEST_SUITE_END();
};
@@ -194,6 +210,177 @@ void FirebirdTest::testTdf153057()
}
}
/**
* Test for tdf#153057: a range filter on a TIME column built via
* XSingleSelectQueryComposer::setStructuredFilter(). This exercises
* OPredicateInputController -> OSQLParser::buildDate() ->
* DBTypeConversion::toTimeString(), a different code path from
* testTdf153057()'s setString() test above. Before the fix,
* a whole-second TIME value got ".000000000" into
* the generated SQL, which Firebird rejects.
*/
void FirebirdTest::testTdf153057_RangeFilter()
{
createTempCopy(u"firebird_empty.odb");
uno::Reference<XOfficeDatabaseDocument> xDocument = getDocumentForUrl(maTempFile.GetURL());
uno::Reference<XConnection> xConnection = getConnectionForDocument(xDocument);
CPPUNIT_ASSERT(xConnection.is());
uno::Reference<XStatement> xStmt = xConnection->createStatement();
xStmt->execute(u"CREATE TABLE \"DURATIONS\" ("
" \"ID\" INTEGER NOT NULL PRIMARY KEY,"
" \"T\" TIME)"_ustr);
xStmt->execute(u"INSERT INTO \"DURATIONS\" VALUES(1, '00:01:00')"_ustr);
xStmt->execute(u"INSERT INTO \"DURATIONS\" VALUES(2, '00:03:00')"_ustr);
xStmt->execute(u"INSERT INTO \"DURATIONS\" VALUES(3, '00:05:00')"_ustr);
xConnection->commit();
// A table created directly via SQL isn't visible to the connection's
// cached table container until it's explicitly refreshed (matches the
// "Refresh Tables" UI command). Without this, the composer below can't
// resolve "T" as a typed select column and silently falls back to an
// untyped/unquoted filter-value path.
uno::Reference<sdbcx::XTablesSupplier> xTablesSupplier(xConnection, UNO_QUERY_THROW);
uno::Reference<util::XRefreshable> xTablesRefresh(xTablesSupplier->getTables(), UNO_QUERY_THROW);
xTablesRefresh->refresh();
uno::Reference<lang::XMultiServiceFactory> xFactory(xConnection, UNO_QUERY_THROW);
uno::Reference<XSingleSelectQueryComposer> xComposer(
xFactory->createInstance(u"com.sun.star.sdb.SingleSelectQueryComposer"_ustr),
UNO_QUERY_THROW);
xComposer->setQuery(u"SELECT \"ID\", \"T\" FROM \"DURATIONS\""_ustr);
beans::PropertyValue aLower, aUpper;
aLower.Name = u"\"T\""_ustr;
aLower.Handle = SQLFilterOperator::GREATER_EQUAL;
aLower.Value <<= u"00:02:00"_ustr;
aUpper.Name = u"\"T\""_ustr;
aUpper.Handle = SQLFilterOperator::LESS_EQUAL;
aUpper.Value <<= u"00:04:00"_ustr;
Sequence<Sequence<beans::PropertyValue>> aFilter{ { aLower, aUpper } };
// Before the fix: SQLException "conversion error from string ..." here,
// because the generated literal was "... AND \"T\" <= '00:04:00.000000000'".
xComposer->setStructuredFilter(aFilter);
uno::Reference<XStatement> xQueryStmt = xConnection->createStatement();
uno::Reference<XResultSet> xRS = xQueryStmt->executeQuery(xComposer->getQuery());
uno::Reference<XRow> xRow(xRS, UNO_QUERY_THROW);
CPPUNIT_ASSERT_MESSAGE("range filter: expected a row", xRS->next());
CPPUNIT_ASSERT_EQUAL_MESSAGE("range filter: wrong row returned", sal_Int32(2), xRow->getInt(1));
CPPUNIT_ASSERT_MESSAGE("range filter: expected exactly one row", !xRS->next());
}
/**
* Regression test for a fractional-seconds TIME filter, distinct from
* testTdf153057_RangeFilter() above.
*/
void FirebirdTest::testTdf153057_FractionalFilter()
{
createTempCopy(u"firebird_empty.odb");
uno::Reference<XOfficeDatabaseDocument> xDocument = getDocumentForUrl(maTempFile.GetURL());
uno::Reference<XConnection> xConnection = getConnectionForDocument(xDocument);
CPPUNIT_ASSERT(xConnection.is());
uno::Reference<XStatement> xStmt = xConnection->createStatement();
xStmt->execute(u"CREATE TABLE \"DURATIONS2\" ("
" \"ID\" INTEGER NOT NULL PRIMARY KEY,"
" \"T\" TIME)"_ustr);
xStmt->execute(u"INSERT INTO \"DURATIONS2\" VALUES(1, '00:01:00')"_ustr);
xStmt->execute(u"INSERT INTO \"DURATIONS2\" VALUES(2, '00:03:00.1235')"_ustr);
xStmt->execute(u"INSERT INTO \"DURATIONS2\" VALUES(3, '00:05:00')"_ustr);
xConnection->commit();
uno::Reference<sdbcx::XTablesSupplier> xTablesSupplier(xConnection, UNO_QUERY_THROW);
uno::Reference<util::XRefreshable> xTablesRefresh(xTablesSupplier->getTables(), UNO_QUERY_THROW);
xTablesRefresh->refresh();
uno::Reference<lang::XMultiServiceFactory> xFactory(xConnection, UNO_QUERY_THROW);
uno::Reference<XSingleSelectQueryComposer> xComposer(
xFactory->createInstance(u"com.sun.star.sdb.SingleSelectQueryComposer"_ustr),
UNO_QUERY_THROW);
xComposer->setQuery(u"SELECT \"ID\", \"T\" FROM \"DURATIONS2\""_ustr);
// A value with genuine sub-decisecond precision (6 significant fractional
// digits) should be rounded to 4 digits for Firebird
beans::PropertyValue aEquals;
aEquals.Name = u"\"T\""_ustr;
aEquals.Handle = SQLFilterOperator::EQUAL;
aEquals.Value <<= u"00:03:00.123456"_ustr;
Sequence<Sequence<beans::PropertyValue>> aFilter{ { aEquals } };
xComposer->setStructuredFilter(aFilter);
uno::Reference<XStatement> xQueryStmt = xConnection->createStatement();
uno::Reference<XResultSet> xRS = xQueryStmt->executeQuery(xComposer->getQuery());
uno::Reference<XRow> xRow(xRS, UNO_QUERY_THROW);
CPPUNIT_ASSERT_MESSAGE("fractional filter: expected a row", xRS->next());
CPPUNIT_ASSERT_EQUAL_MESSAGE("fractional filter: wrong row returned", sal_Int32(2), xRow->getInt(1));
CPPUNIT_ASSERT_MESSAGE("fractional filter: expected exactly one row", !xRS->next());
}
/**
* Regression test for tdf#173589: filtering a TIME column via the Standard
* Filter dialog on a raw table (Table Data View) returned an
* empty result.
*/
void FirebirdTest::testTdf173589_TableStandardFilter()
{
createTempCopy(u"firebird_empty.odb");
uno::Reference<XOfficeDatabaseDocument> xDocument = getDocumentForUrl(maTempFile.GetURL());
uno::Reference<XConnection> xConnection = getConnectionForDocument(xDocument);
CPPUNIT_ASSERT(xConnection.is());
uno::Reference<XStatement> xStmt = xConnection->createStatement();
xStmt->execute(u"CREATE TABLE \"TITLES\" ("
" \"ID\" INTEGER NOT NULL PRIMARY KEY,"
" \"Duration\" TIME)"_ustr);
xStmt->execute(u"INSERT INTO \"TITLES\" VALUES(1, '00:01:00')"_ustr);
xStmt->execute(u"INSERT INTO \"TITLES\" VALUES(2, '00:05:00')"_ustr);
xStmt->execute(u"INSERT INTO \"TITLES\" VALUES(3, '00:09:00')"_ustr);
xConnection->commit();
uno::Reference<sdbcx::XTablesSupplier> xTablesSupplier(xConnection, UNO_QUERY_THROW);
uno::Reference<util::XRefreshable> xTablesRefresh(xTablesSupplier->getTables(), UNO_QUERY_THROW);
xTablesRefresh->refresh();
uno::Reference<lang::XMultiServiceFactory> xFactory(xConnection, UNO_QUERY_THROW);
uno::Reference<XSingleSelectQueryComposer> xComposer(
xFactory->createInstance(u"com.sun.star.sdb.SingleSelectQueryComposer"_ustr),
UNO_QUERY_THROW);
xComposer->setQuery(u"SELECT \"ID\", \"Duration\" FROM \"TITLES\""_ustr);
uno::Reference<container::XNameAccess> xColumns(
uno::Reference<sdbcx::XColumnsSupplier>(xComposer, UNO_QUERY_THROW)->getColumns());
uno::Reference<beans::XPropertySet> xColumn(xColumns->getByName(u"Duration"_ustr), UNO_QUERY_THROW);
::dbtools::OPredicateInputController aPredicateInput(getComponentContext(), xConnection);
OUString sPredicateValue;
aPredicateInput.getPredicateValue(u"00:05:00"_ustr, xColumn) >>= sPredicateValue;
CPPUNIT_ASSERT_MESSAGE("tdf173589: predicate value must not be empty", !sPredicateValue.isEmpty());
beans::PropertyValue aFilter;
aFilter.Name = u"\"Duration\""_ustr;
aFilter.Handle = SQLFilterOperator::LESS;
aFilter.Value <<= sPredicateValue;
Sequence<Sequence<beans::PropertyValue>> aFilterSeq{ { aFilter } };
xComposer->setStructuredFilter(aFilterSeq);
uno::Reference<XStatement> xQueryStmt = xConnection->createStatement();
uno::Reference<XResultSet> xRS = xQueryStmt->executeQuery(xComposer->getQuery());
uno::Reference<XRow> xRow(xRS, UNO_QUERY_THROW);
CPPUNIT_ASSERT_MESSAGE("tdf173589: expected a row", xRS->next());
CPPUNIT_ASSERT_EQUAL_MESSAGE("tdf173589: wrong row returned", sal_Int32(1), xRow->getInt(1));
CPPUNIT_ASSERT_MESSAGE("tdf173589: expected exactly one row", !xRS->next());
}
CPPUNIT_TEST_SUITE_REGISTRATION(FirebirdTest);
CPPUNIT_PLUGIN_IMPLEMENT();
@@ -1689,7 +1689,7 @@ void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropert
case DataType::VARCHAR:
case DataType::CHAR:
case DataType::LONGVARCHAR:
aSQL.append( DBTypeConversion::toSQLString( nType, aValue, m_xTypeConverter ) );
aSQL.append( DBTypeConversion::toSQLString( nType, aValue, m_xTypeConverter, m_xConnection ) );
break;
case DataType::CLOB:
{
@@ -1704,7 +1704,7 @@ void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropert
}
else
{
aSQL.append( DBTypeConversion::toSQLString( nType, aValue, m_xTypeConverter ) );
aSQL.append( DBTypeConversion::toSQLString( nType, aValue, m_xTypeConverter, m_xConnection ) );
}
}
break;
@@ -1737,7 +1737,7 @@ void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropert
}
break;
default:
aSQL.append( DBTypeConversion::toSQLString( nType, aValue, m_xTypeConverter ) );
aSQL.append( DBTypeConversion::toSQLString( nType, aValue, m_xTypeConverter, m_xConnection ) );
break;
}
}
+17 -3
View File
@@ -1361,8 +1361,14 @@ FeatureState SbaXDataBrowserController::GetState(sal_uInt16 nId) const
aReturn.bEnabled = false;
return aReturn;
}
{
Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
OUString sFilter, sHaving;
xFormSet->getPropertyValue(PROPERTY_FILTER) >>= sFilter;
xFormSet->getPropertyValue(PROPERTY_HAVING_CLAUSE) >>= sHaving;
// any filter or sort order set ?
aReturn.bEnabled = m_xParser->getFilter().getLength() || m_xParser->getHavingClause().getLength() || m_xParser->getOrder().getLength();
aReturn.bEnabled = !sFilter.isEmpty() || !sHaving.isEmpty() || m_xParser->getOrder().getLength();
}
return aReturn;
}
// no chance without valid models
@@ -1705,8 +1711,16 @@ void SbaXDataBrowserController::ExecuteFilterSortCrit(bool bFilter)
Reference< XPropertySet > xFormSet(getRowSet(), UNO_QUERY);
const OUString sOldVal = bFilter ? m_xParser->getFilter() : m_xParser->getOrder();
const OUString sOldHaving = m_xParser->getHavingClause();
OUString sOldVal, sOldHaving;
if (bFilter)
{
xFormSet->getPropertyValue(PROPERTY_FILTER) >>= sOldVal;
xFormSet->getPropertyValue(PROPERTY_HAVING_CLAUSE) >>= sOldHaving;
}
else
{
sOldVal = m_xParser->getOrder();
}
Reference< XSingleSelectQueryComposer > xParser = createParser_nothrow();
try
{
@@ -2968,7 +2968,8 @@ std::unique_ptr<OSQLParseNode> OQueryDesignView::getPredicateTreeFromEntry(const
_sCriteria,
static_cast<OQueryController&>(getController()).getNumberFormatter(),
_rxColumn,
false);
false,
static_cast<OQueryController&>(getController()).getConnection());
return pParseNode;
}
@@ -1145,7 +1145,9 @@ bool OSelectionBrowseBox::SaveModified()
pParseNode = rParser.predicateTree(aErrorMsg,
aText,
static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
xColumn);
xColumn,
/*bUseRealName*/true,
static_cast<OQueryController&>(getDesignView()->getController()).getConnection());
if (pParseNode)
{
pParseNode->parseNodeToPredicateStr(aCrit,
+17 -22
View File
@@ -44,8 +44,8 @@ BZIP2_TARBALL := bzip2-1.0.8.tar.gz
# three static lines
# so that git cherry-pick
# will not run into conflicts
CAIRO_SHA256SUM := 445ed8208a6e4823de1226a74ca319d3600e83f6369f99b14265006599c32ccb
CAIRO_VERSION_MICRO := 4
CAIRO_SHA256SUM := 1c767308174337a74694da0f3ec069c271452163a1ef4540964c50c301f157d4
CAIRO_VERSION_MICRO := 6
CAIRO_TARBALL := cairo-1.18.$(CAIRO_VERSION_MICRO).tar.xz
# three static lines
# so that git cherry-pick
@@ -116,13 +116,13 @@ ETONYEK_TARBALL := libetonyek-0.1.$(ETONYEK_VERSION_MICRO).tar.xz
# three static lines
# so that git cherry-pick
# will not run into conflicts
EXPAT_SHA256SUM := 656ae1cc8da3b4ea513bb4e254f33e6243938084c0ec6239da873376b09985a7
EXPAT_TARBALL := expat-2.8.4.tar.xz
EXPAT_SHA256SUM := 1e727b8933ec51a77a9a9d9afcf8e688bce45d907c13e36ab7393fe36e703182
EXPAT_TARBALL := expat-2.8.5.tar.xz
# three static lines
# so that git cherry-pick
# will not run into conflicts
FIREBIRD_SHA256SUM := bd263c4f685fb8fc3f1dcb8be8a411033cc31c5404d1dfce5d3849aa3f63a64d
FIREBIRD_TARBALL := Firebird-3.0.13.33818-0.tar.bz2
FIREBIRD_SHA256SUM := dce3f26c0f015b3c40f36085f8cc21de58dd568e0f347fdd0fcc7942deda8cff
FIREBIRD_TARBALL := Firebird-3.0.14.33856-0.tar.bz2
# three static lines
# so that git cherry-pick
# will not run into conflicts
@@ -257,11 +257,6 @@ FONT_REEM_TARBALL := ReemKufi-2.0.zip
# three static lines
# so that git cherry-pick
# will not run into conflicts
FONT_SCHEHERAZADE_SHA256SUM := 251c8817ceb87d9b661ce1d5b49e732a0116add10abc046be4b8ba5196e149b5
FONT_SCHEHERAZADE_TARBALL := Scheherazade-2.100.zip
# three static lines
# so that git cherry-pick
# will not run into conflicts
FREEHAND_SHA256SUM := 350b10d24a76d7e8c8ae98b74c2d432a2c8ddec08935d09856d20b695a35e600
FREEHAND_TARBALL := libfreehand-0.1.4.tar.xz
# three static lines
@@ -292,8 +287,8 @@ GRAPHITE_TARBALL := graphite2-minimal-1.3.15.tgz
# three static lines
# so that git cherry-pick
# will not run into conflicts
HARFBUZZ_SHA256SUM := 2357ed966c6ced7bfa720b0640c0231065af01158fbea215093ffa15aed44371
HARFBUZZ_TARBALL := harfbuzz-14.4.0.tar.xz
HARFBUZZ_SHA256SUM := b7132e148358a45185c9feafd049dbaf243649d3c44414b3534d9c95d18592b9
HARFBUZZ_TARBALL := harfbuzz-14.5.0.tar.xz
# three static lines
# so that git cherry-pick
# will not run into conflicts
@@ -307,8 +302,8 @@ HSQLDB_TARBALL := 17410483b5b5f267aa18b7e00b65e6e0-hsqldb_1_8_0.zip
# three static lines
# so that git cherry-pick
# will not run into conflicts
HUNSPELL_SHA256SUM := 433274dac0619cb00c2e18b43a3dd3a9d50da5b5613fa9b5c21781e35dd76bc1
HUNSPELL_TARBALL := hunspell-1.7.3.tar.gz
HUNSPELL_SHA256SUM := 66ec82a577395fe9d471504267e6dd04615c76517c61af7c6b9c19e5e34e73c8
HUNSPELL_TARBALL := hunspell-1.7.4.tar.gz
# three static lines
# so that git cherry-pick
# will not run into conflicts
@@ -365,8 +360,8 @@ LIBJPEG_TURBO_TARBALL := libjpeg-turbo-3.1.4.1.tar.gz
# three static lines
# so that git cherry-pick
# will not run into conflicts
LANGTAGREG_SHA256SUM := 48293d95a13372f3e5bae04890d7d54ef4168b2469060e8e49cf60461cfc616f
LANGTAGREG_TARBALL := language-subtag-registry-2026-08-08.tar.bz2
LANGTAGREG_SHA256SUM := 10223cc8c219427c86a4c66ce98282a00c7f4d9b0609355146282344783007f2
LANGTAGREG_TARBALL := language-subtag-registry-2026-9-17.tar.bz2
# three static lines
# so that git cherry-pick
# will not run into conflicts
@@ -493,8 +488,8 @@ MYTHES_TARBALL := mythes-1.2.6.tar.xz
# three static lines
# so that git cherry-pick
# will not run into conflicts
NSS_SHA256SUM := d389064d5e5ef09d597f8ae8dadc066f71e97b982bd7418b835686425fc3a189
NSS_TARBALL := nss-3.129-with-nspr-4.39.tar.gz
NSS_SHA256SUM := d122bd039416254567f2dfe7f4c9b6ed4d202d8c6a3ed91332da0d514d0974c0
NSS_TARBALL := nss-3.130-with-nspr-4.39.tar.gz
# three static lines
# so that git cherry-pick
# will not run into conflicts
@@ -592,7 +587,7 @@ PYTHON_TARBALL := Python-3.13.15.tar.xz
# so that git cherry-pick
# will not run into conflicts
QUICKJS_SHA256SUM := 866bad1e2f148b6f8144a4a3d4c3f8a0754495a6920fe56a7dd698cf0ad27f65
QUICKJS_TARBALL := quickjs-0.16.2-amalgam.zip
QUICKJS_TARBALL := quickjs-0.17.0-amalgam.zip
# three static lines
# so that git cherry-pick
# will not run into conflicts
@@ -627,8 +622,8 @@ REVENGE_TARBALL := librevenge-0.0.$(REVENGE_VERSION_MICRO).tar.bz2
# three static lines
# so that git cherry-pick
# will not run into conflicts
MD4C_SHA256SUM := 353c346f376b87c954a13f3415ede2d51264cc61dc5abcd38ff1d2aa0d059b9e
MD4C_TARBALL := md4c-release-0.5.3.tar.gz
MD4C_SHA256SUM := 4d151298125a81da3b2efa2e0eed8bdb7a9318569804e4fa4d7a2375ab83ef70
MD4C_TARBALL := md4c-0.6.0.tar.gz
# three static lines
# so that git cherry-pick
# will not run into conflicts
@@ -37,6 +37,7 @@ $(eval $(call gb_CppunitTest_use_externals,drawinglayer_processors,\
))
$(eval $(call gb_CppunitTest_add_exception_objects,drawinglayer_processors, \
drawinglayer/qa/unit/strokeattribute \
drawinglayer/qa/unit/vclmetafileprocessor2d \
drawinglayer/qa/unit/vclpixelprocessor2d \
))
+78
View File
@@ -0,0 +1,78 @@
/* -*- 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/.
*/
#include <cppunit/TestAssert.h>
#include <test/bootstrapfixture.hxx>
#include <drawinglayer/attribute/strokeattribute.hxx>
using namespace drawinglayer::attribute;
namespace
{
class StrokeAttributeTest : public test::BootstrapFixture
{
};
CPPUNIT_TEST_FIXTURE(StrokeAttributeTest, tdf152997_odd_length_dash_array)
{
std::vector<double> aDashArray{ 6.0 };
StrokeAttribute aStroke(std::move(aDashArray));
// Without the fix in place, this test would have failed with
// - Expected: 2
// - Actual : 1
// i.e. the odd-length array was not duplicated
const std::vector<double> aExpected{ 6.0, 6.0 };
CPPUNIT_ASSERT_EQUAL(aExpected.size(), aStroke.getDotDashArray().size());
CPPUNIT_ASSERT_EQUAL(12.0, aStroke.getFullDotDashLen());
for (size_t i = 0; i < aExpected.size(); ++i)
CPPUNIT_ASSERT_DOUBLES_EQUAL(aExpected[i], aStroke.getDotDashArray()[i], 1E-12);
}
CPPUNIT_TEST_FIXTURE(StrokeAttributeTest, tdf152997_odd_length_dash_array_multiple_values)
{
std::vector<double> aDashArray{ 5.0, 3.0, 2.0 };
StrokeAttribute aStroke(std::move(aDashArray));
// Without the fix in place, this test would have failed with
// - Expected: 6
// - Actual : 3
// i.e. the odd-length array was not duplicated
const std::vector<double> aExpected{ 5.0, 3.0, 2.0, 5.0, 3.0, 2.0 };
CPPUNIT_ASSERT_EQUAL(aExpected.size(), aStroke.getDotDashArray().size());
for (size_t i = 0; i < aExpected.size(); ++i)
CPPUNIT_ASSERT_DOUBLES_EQUAL(aExpected[i], aStroke.getDotDashArray()[i], 1E-12);
}
CPPUNIT_TEST_FIXTURE(StrokeAttributeTest, tdf152997_even_length_dash_array)
{
std::vector<double> aDashArray{ 4.0, 2.0 };
StrokeAttribute aStroke(std::move(aDashArray), 6.0);
// An even-length dash array should not be changed
const std::vector<double> aExpected{ 4.0, 2.0 };
CPPUNIT_ASSERT_EQUAL(aExpected.size(), aStroke.getDotDashArray().size());
CPPUNIT_ASSERT_EQUAL(6.0, aStroke.getFullDotDashLen());
for (size_t i = 0; i < aExpected.size(); ++i)
CPPUNIT_ASSERT_DOUBLES_EQUAL(aExpected[i], aStroke.getDotDashArray()[i], 1E-12);
}
CPPUNIT_TEST_FIXTURE(StrokeAttributeTest, tdf152997_empty_dash_array)
{
std::vector<double> aDashArray;
StrokeAttribute aStroke(std::move(aDashArray));
// An empty dash array should not be changed
CPPUNIT_ASSERT(aStroke.getDotDashArray().empty());
}
} // namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -36,6 +36,21 @@ namespace drawinglayer::attribute
: maDotDashArray(std::move(rDotDashArray)),
mfFullDotDashLen(fFullDotDashLen)
{
// tdf#152997 - duplicate an odd length dash array in order to meet the spec.
// An odd-length array will be drawn as one dash spanning the entire path. The
// specifications under https://www.w3.org/TR/svg-strokes/#StrokeDashing state:
// "If the list has an odd number of values, then it is repeated to yield an
// even number of values. Thus, the rendering behavior of stroke-dasharray: 5,3,2
// is equivalent to stroke-dasharray: 5,3,2,5,3,2."
if (maDotDashArray.size() % 2 == 1)
{
const std::vector<double> aOriginal(maDotDashArray);
maDotDashArray.insert(maDotDashArray.end(), aOriginal.begin(), aOriginal.end());
// Increase the length accordingly
if (0.0 != mfFullDotDashLen)
mfFullDotDashLen *= 2.0;
}
}
ImpStrokeAttribute()
@@ -19,7 +19,7 @@
#include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <vcl/pdfwriter.hxx>
using namespace com::sun::star;
@@ -53,26 +53,27 @@ namespace drawinglayer::primitive2d
{
const StructureTagPrimitive2D& rCompare = static_cast<const StructureTagPrimitive2D&>(rPrimitive);
return (isBackground() == rCompare.isBackground() &&
isImage() == rCompare.isImage());
return (getStructureElement() == rCompare.getStructureElement()
&& isBackground() == rCompare.isBackground()
&& isImage() == rCompare.isImage()
&& isDecorative() == rCompare.isDecorative());
}
return false;
}
bool StructureTagPrimitive2D::opensStructureElement() const
{
return !isDecorative() && !isBackground()
&& vcl::pdf::StructElement::NonStructElement != getStructureElement();
}
// provide unique ID
sal_uInt32 StructureTagPrimitive2D::getPrimitive2DID() const
{
return PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D;
}
bool StructureTagPrimitive2D::isTaggedSdrObject() const
{
// note at the moment *all* StructureTagPrimitive2D are created for
// SdrObjects - if that ever changes, need another condition here
return !isBackground() || isImage();
}
} // end of namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -957,10 +957,8 @@ void VclMetafileProcessor2D::processObjectInfoPrimitive2D(
// tdf#154982 process content first, so this object overrides any nested one
process(rObjectInfoPrimitive2D.getChildren());
// currently StructureTagPrimitive2D is only used for SdrObjects - have to
// avoid adding Alt text if the SdrObject is not actually tagged, as it
// would then end up on an unrelated structure element.
if (mpCurrentStructureTag && mpCurrentStructureTag->isTaggedSdrObject())
// alt text belongs to the element this tag opens
if (mpCurrentStructureTag && mpCurrentStructureTag->opensStructureElement())
{
// Create image alternative description from ObjectInfoPrimitive2D info
// for PDF export, for the currently active SdrObject's structure element
@@ -2754,20 +2752,20 @@ void VclMetafileProcessor2D::processStructureTagPrimitive2D(
::comphelper::ValueRestorationGuard const g(mpCurrentStructureTag, &rStructureTagCandidate);
// structured tag primitive
const vcl::pdf::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
bool bTagUsed((vcl::pdf::StructElement::NonStructElement != rTagElement));
const bool bArtifact(
rStructureTagCandidate.isDecorative()
|| (rStructureTagCandidate.isBackground() && rStructureTagCandidate.isImage()));
// a plain background object is neither, and goes out untagged
const bool bTagUsed(bArtifact || rStructureTagCandidate.opensStructureElement());
::std::optional<sal_Int32> oAnchorParent;
if (!rStructureTagCandidate.isTaggedSdrObject())
{
bTagUsed = false;
}
if (mpPDFExtOutDevData && bTagUsed)
{
// foreground object: tag as regular structure element
if (!rStructureTagCandidate.isBackground())
if (!bArtifact)
{
const vcl::pdf::StructElement& rTagElement(
rStructureTagCandidate.getStructureElement());
if (rStructureTagCandidate.GetAnchorStructureElementKey() != nullptr)
{
sal_Int32 const id = mpPDFExtOutDevData->EnsureStructureElement(
@@ -2834,16 +2832,10 @@ void VclMetafileProcessor2D::processStructureTagPrimitive2D(
vcl::pdf::PDFWriter::Column);
}
}
// background object
else
{
// background image: tag as artifact
if (rStructureTagCandidate.isImage())
mpPDFExtOutDevData->WrapBeginStructureElement(
vcl::pdf::StructElement::NonStructElement);
// any other background object: do not tag
else
assert(false);
}
}
@@ -1844,6 +1844,19 @@ namespace emfplushelper
}
rMS.ReadUInt32(rectangles);
// The record that is left says how many rectangles there can really be,
// whatever count the file gave.
const sal_uInt32 nBytesPerRectangle = (flags & 0x4000) ? 8 : 16;
const sal_uInt64 nRecordLeft
= rMS.Tell() < next ? std::min(next - rMS.Tell(), rMS.remainingSize())
: 0;
const sal_uInt64 nMaxRectangles = nRecordLeft / nBytesPerRectangle;
if (rectangles > nMaxRectangles)
{
SAL_WARN("drawinglayer.emf", "EMF+\twants " << rectangles
<< " rectangles, the record holds " << nMaxRectangles);
rectangles = static_cast<sal_uInt32>(nMaxRectangles);
}
for (sal_uInt32 i = 0; i < rectangles; i++)
{
ReadRectangle(rMS, x, y, width, height, bool(flags & 0x4000));
@@ -1931,6 +1944,16 @@ namespace emfplushelper
"EMF+\t Bezier Draw not support number of points other than 4, 7, "
"10, 13, 16...");
const sal_uInt32 nBytesPerPoint = (flags & 0x4000) ? 4 : 8;
const sal_uInt64 nRecordLeft = rMS.Tell() < next ? next - rMS.Tell() : 0;
const sal_uInt64 nMaxPoints = nRecordLeft / nBytesPerPoint;
if (aCount > nMaxPoints)
{
SAL_WARN("drawinglayer.emf", "EMF+\twants " << aCount
<< " points, the record holds " << nMaxPoints);
aCount = static_cast<sal_uInt32>(nMaxPoints);
}
if (aCount < 4)
{
SAL_WARN("drawinglayer.emf", "EMF+\t Bezier Draw does not support less "
@@ -2092,9 +2092,7 @@ uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getDe
xPropSet->SetSelection( MakeSelection( 0, GetTextLen() ) );
uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
if (!xPropSetInfo.is())
throw uno::RuntimeException(u"Cannot query XPropertySetInfo"_ustr,
uno::Reference< uno::XInterface >
( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy
throw uno::RuntimeException(u"Cannot query XPropertySetInfo"_ustr, getXWeak());
// build sequence of available properties to check
uno::Sequence< beans::Property > aProperties;
@@ -2178,9 +2176,7 @@ uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getRu
xPropSet->SetSelection( MakeSelection( nIndex ) );
uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
if (!xPropSetInfo.is())
throw uno::RuntimeException(u"Cannot query XPropertySetInfo"_ustr,
uno::Reference< uno::XInterface >
( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy
throw uno::RuntimeException(u"Cannot query XPropertySetInfo"_ustr, getXWeak());
// build sequence of available properties to check
uno::Sequence< beans::Property > aProperties;
@@ -168,9 +168,7 @@ awt::Rectangle AccessibleImageBullet::implGetBounds( )
void SAL_CALL AccessibleImageBullet::grabFocus( )
{
throw uno::RuntimeException(u"Not focusable"_ustr,
uno::Reference< uno::XInterface >
( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy
throw uno::RuntimeException(u"Not focusable"_ustr, getXWeak());
}
sal_Int32 SAL_CALL AccessibleImageBullet::getForeground( )
+58 -58
View File
@@ -87,14 +87,14 @@ const XParaPortion& XParaPortionList::operator [](size_t i) const
return *maList[i];
}
ContentInfo::ContentInfo( SfxItemPool& rPool ) :
EditEngineParagraph::EditEngineParagraph( SfxItemPool& rPool ) :
eFamily(SfxStyleFamily::Para),
aParaAttribs(SfxItemSet::makeFixedSfxItemSet<EE_PARA_START, EE_CHAR_END>(rPool))
{
}
// the real Copy constructor is nonsense, since I have to work with another Pool!
ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse ) :
EditEngineParagraph::EditEngineParagraph( const EditEngineParagraph& rCopyFrom, SfxItemPool& rPoolToUse ) :
maText(rCopyFrom.maText),
aStyle(rCopyFrom.aStyle),
eFamily(rCopyFrom.eFamily),
@@ -115,35 +115,35 @@ ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse
mpWrongs.reset(rCopyFrom.GetWrongList()->Clone());
}
ContentInfo::~ContentInfo()
EditEngineParagraph::~EditEngineParagraph()
{
maCharAttribs.clear();
}
void ContentInfo::NormalizeString( svl::SharedStringPool& rPool )
void EditEngineParagraph::NormalizeString( svl::SharedStringPool& rPool )
{
maText = rPool.intern(OUString(maText.getData()));
}
OUString ContentInfo::GetText() const
OUString EditEngineParagraph::GetText() const
{
rtl_uString* p = const_cast<rtl_uString*>(maText.getData());
return OUString(p);
}
sal_Int32 ContentInfo::GetTextLen() const
sal_Int32 EditEngineParagraph::GetTextLen() const
{
const rtl_uString* p = maText.getData();
return p->length;
}
void ContentInfo::SetText( const OUString& rStr )
void EditEngineParagraph::SetText( const OUString& rStr )
{
maText = svl::SharedString(rStr.pData, nullptr);
}
void ContentInfo::dumpAsXml(xmlTextWriterPtr pWriter) const
void EditEngineParagraph::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentInfo"));
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("style"), BAD_CAST(aStyle.toUtf8().getStr()));
@@ -167,18 +167,18 @@ void ContentInfo::dumpAsXml(xmlTextWriterPtr pWriter) const
(void)xmlTextWriterEndElement(pWriter);
}
const WrongList* ContentInfo::GetWrongList() const
const WrongList* EditEngineParagraph::GetWrongList() const
{
return mpWrongs.get();
}
void ContentInfo::SetWrongList( WrongList* p )
void EditEngineParagraph::SetWrongList( WrongList* p )
{
mpWrongs.reset(p);
}
// #i102062#
bool ContentInfo::isWrongListEqual(const ContentInfo& rCompare) const
bool EditEngineParagraph::isWrongListEqual(const EditEngineParagraph& rCompare) const
{
if(GetWrongList() == rCompare.GetWrongList())
return true;
@@ -190,7 +190,7 @@ bool ContentInfo::isWrongListEqual(const ContentInfo& rCompare) const
}
#if DEBUG_EDIT_ENGINE
void ContentInfo::Dump() const
void EditEngineParagraph::Dump() const
{
cout << "--" << endl;
cout << "text: '" << OUString(const_cast<rtl_uString*>(maText.getData())) << "'" << endl;
@@ -205,7 +205,7 @@ void ContentInfo::Dump() const
}
#endif
bool ContentInfo::Equals(const ContentInfo& rCompare, bool bComparePool) const
bool EditEngineParagraph::Equals(const EditEngineParagraph& rCompare, bool bComparePool) const
{
return maText == rCompare.maText && aStyle == rCompare.aStyle && eFamily == rCompare.eFamily
&& aParaAttribs.Equals(rCompare.aParaAttribs, bComparePool)
@@ -236,7 +236,7 @@ void EditTextObject::dumpAsXml(xmlTextWriterPtr pWriter) const
sal_Int32 nCount = GetParagraphCount();
for (sal_Int32 i = 0; i < nCount; ++i)
{
maContents[i]->dumpAsXml(pWriter);
maParagraphs[i]->dumpAsXml(pWriter);
}
(void)xmlTextWriterEndElement(pWriter);
@@ -292,9 +292,9 @@ EditTextObject::EditTextObject( const EditTextObject& r )
{
// Do not copy PortionInfo
maContents.reserve(r.maContents.size());
for (auto const& content : r.maContents)
maContents.push_back(std::unique_ptr<ContentInfo>(new ContentInfo(*content, *mpPool)));
maParagraphs.reserve(r.maParagraphs.size());
for (auto const& content : r.maParagraphs)
maParagraphs.push_back(std::unique_ptr<EditEngineParagraph>(new EditEngineParagraph(*content, *mpPool)));
}
EditTextObject::EditTextObject( EditTextObject&& ) noexcept = default;
@@ -305,7 +305,7 @@ EditTextObject::~EditTextObject()
// Remove contents before deleting the pool instance since each content
// has to access the pool instance in its destructor.
maContents.clear();
maParagraphs.clear();
}
EditTextObject& EditTextObject::operator=(EditTextObject&&) = default;
@@ -317,9 +317,9 @@ void EditTextObject::SetUserType( OutlinerMode n )
void EditTextObject::NormalizeString( svl::SharedStringPool& rPool )
{
for (auto const& content : maContents)
for (auto const& content : maParagraphs)
{
ContentInfo& rInfo = *content;
EditEngineParagraph& rInfo = *content;
rInfo.NormalizeString(rPool);
}
}
@@ -327,10 +327,10 @@ void EditTextObject::NormalizeString( svl::SharedStringPool& rPool )
std::vector<svl::SharedString> EditTextObject::GetSharedStrings() const
{
std::vector<svl::SharedString> aSSs;
aSSs.reserve(maContents.size());
for (auto const& content : maContents)
aSSs.reserve(maParagraphs.size());
for (auto const& content : maParagraphs)
{
const ContentInfo& rInfo = *content;
const EditEngineParagraph& rInfo = *content;
aSSs.push_back(rInfo.GetSharedString());
}
return aSSs;
@@ -376,15 +376,15 @@ TextRotation EditTextObject::GetRotation() const
return meRotation;
}
ContentInfo* EditTextObject::CreateAndInsertContent()
EditEngineParagraph* EditTextObject::CreateAndInsertParagraph()
{
maContents.push_back(std::unique_ptr<ContentInfo>(new ContentInfo(*mpPool)));
return maContents.back().get();
maParagraphs.push_back(std::unique_ptr<EditEngineParagraph>(new EditEngineParagraph(*mpPool)));
return maParagraphs.back().get();
}
sal_Int32 EditTextObject::GetParagraphCount() const
{
size_t nSize = maContents.size();
size_t nSize = maParagraphs.size();
if (nSize > EE_PARA_MAX)
{
SAL_WARN( "editeng", "EditTextObject::GetParagraphCount - overflow " << nSize);
@@ -395,12 +395,12 @@ sal_Int32 EditTextObject::GetParagraphCount() const
OUString EditTextObject::GetText(sal_Int32 nPara) const
{
return maContents[nPara]->GetText();
return maParagraphs[nPara]->GetText();
}
OUString EditTextObject::GetText(LineEnd eEnd) const
{
const size_t nParas = maContents.size();
const size_t nParas = maParagraphs.size();
if (nParas == 0)
return OUString();
@@ -412,7 +412,7 @@ OUString EditTextObject::GetText(LineEnd eEnd) const
{
if (!aSep.isEmpty() && nPara > 0)
aBuffer.append(aSep);
aBuffer.append(maContents[nPara]->GetText());
aBuffer.append(maParagraphs[nPara]->GetText());
}
return aBuffer.makeStringAndClear();
@@ -420,37 +420,37 @@ OUString EditTextObject::GetText(LineEnd eEnd) const
sal_Int32 EditTextObject::GetTextLen(sal_Int32 nPara ) const
{
return maContents[nPara]->GetTextLen();
return maParagraphs[nPara]->GetTextLen();
}
sal_Int16 EditTextObject::GetNumberingDepth(sal_Int32 nPara) const
{
return maContents[nPara]->GetNumberingDepth();
return maParagraphs[nPara]->GetNumberingDepth();
}
void EditTextObject::SetNumberingDepth(sal_Int32 nPara, sal_Int16 nDepth)
{
maContents[nPara]->SetNumberingDepth(nDepth);
maParagraphs[nPara]->SetNumberingDepth(nDepth);
}
sal_Int16 EditTextObject::GetNumberingStartValue(sal_Int32 nPara) const
{
return maContents[nPara]->GetNumberingStartValue();
return maParagraphs[nPara]->GetNumberingStartValue();
}
void EditTextObject::SetNumberingStartValue(sal_Int32 nPara, sal_Int16 nStartValue)
{
maContents[nPara]->SetNumberingStartValue(nStartValue);
maParagraphs[nPara]->SetNumberingStartValue(nStartValue);
}
bool EditTextObject::IsNumberingRestart(sal_Int32 nPara) const
{
return maContents[nPara]->IsNumberingRestart();
return maParagraphs[nPara]->IsNumberingRestart();
}
void EditTextObject::SetNumberingRestart(sal_Int32 nPara, bool bRestart)
{
maContents[nPara]->SetNumberingRestart(bRestart);
maParagraphs[nPara]->SetNumberingRestart(bRestart);
}
void EditTextObject::ClearPortionInfo()
@@ -460,7 +460,7 @@ void EditTextObject::ClearPortionInfo()
bool EditTextObject::HasOnlineSpellErrors() const
{
for (auto const& content : maContents)
for (auto const& content : maParagraphs)
{
if ( content->GetWrongList() && !content->GetWrongList()->empty() )
return true;
@@ -471,7 +471,7 @@ bool EditTextObject::HasOnlineSpellErrors() const
void EditTextObject::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const
{
rLst.clear();
const ContentInfo& rC = *maContents[nPara];
const EditEngineParagraph& rC = *maParagraphs[nPara];
for (const XEditAttribute & rAttr : rC.maCharAttribs)
{
EECharAttrib aEEAttr(rAttr.GetStart(), rAttr.GetEnd(), rAttr.GetItem());
@@ -486,9 +486,9 @@ bool EditTextObject::IsFieldObject() const
const SvxFieldItem* EditTextObject::GetField() const
{
if (maContents.size() == 1)
if (maParagraphs.size() == 1)
{
const ContentInfo& rC = *maContents[0];
const EditEngineParagraph& rC = *maParagraphs[0];
if (rC.GetText().getLength() == 1)
{
size_t nAttribs = rC.maCharAttribs.size();
@@ -505,7 +505,7 @@ const SvxFieldItem* EditTextObject::GetField() const
const SvxFieldData* EditTextObject::GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const
{
const ContentInfo& rC = *maContents[nPara];
const EditEngineParagraph& rC = *maParagraphs[nPara];
if (nPos >= rC.maCharAttribs.size())
// URL position is out-of-bound.
return nullptr;
@@ -535,10 +535,10 @@ const SvxFieldData* EditTextObject::GetFieldData(sal_Int32 nPara, size_t nPos, s
bool EditTextObject::HasField( sal_Int32 nType ) const
{
size_t nParagraphs = maContents.size();
size_t nParagraphs = maParagraphs.size();
for (size_t nPara = 0; nPara < nParagraphs; ++nPara)
{
const ContentInfo& rC = *maContents[nPara];
const EditEngineParagraph& rC = *maParagraphs[nPara];
size_t nAttrs = rC.maCharAttribs.size();
for (size_t nAttr = 0; nAttr < nAttrs; ++nAttr)
{
@@ -560,7 +560,7 @@ bool EditTextObject::HasField( sal_Int32 nType ) const
const SfxItemSet& EditTextObject::GetParaAttribs(sal_Int32 nPara) const
{
const ContentInfo& rC = *maContents[nPara];
const EditEngineParagraph& rC = *maParagraphs[nPara];
return rC.GetParaAttribs();
}
@@ -568,9 +568,9 @@ bool EditTextObject::RemoveCharAttribs( sal_uInt16 _nWhich )
{
bool bChanged = false;
for ( size_t nPara = maContents.size(); nPara; )
for ( size_t nPara = maParagraphs.size(); nPara; )
{
ContentInfo& rC = *maContents[--nPara];
EditEngineParagraph& rC = *maParagraphs[--nPara];
for (size_t nAttr = rC.maCharAttribs.size(); nAttr; )
{
@@ -619,13 +619,13 @@ public:
void EditTextObject::GetAllSections( std::vector<editeng::Section>& rAttrs ) const
{
std::vector<editeng::Section> aAttrs;
aAttrs.reserve(maContents.size());
aAttrs.reserve(maParagraphs.size());
std::vector<size_t> aBorders;
for (size_t nPara = 0; nPara < maContents.size(); ++nPara)
for (size_t nPara = 0; nPara < maParagraphs.size(); ++nPara)
{
aBorders.clear();
const ContentInfo& rC = *maContents[nPara];
const EditEngineParagraph& rC = *maParagraphs[nPara];
aBorders.push_back(0);
aBorders.push_back(rC.GetText().getLength());
for (const XEditAttribute & rAttr : rC.maCharAttribs)
@@ -669,9 +669,9 @@ void EditTextObject::GetAllSections( std::vector<editeng::Section>& rAttrs ) con
// Go through all formatted paragraphs, and store format items.
std::vector<editeng::Section>::iterator itAttr = aAttrs.begin();
for (sal_Int32 nPara = 0; nPara < static_cast<sal_Int32>(maContents.size()); ++nPara)
for (sal_Int32 nPara = 0; nPara < static_cast<sal_Int32>(maParagraphs.size()); ++nPara)
{
const ContentInfo& rC = *maContents[nPara];
const EditEngineParagraph& rC = *maParagraphs[nPara];
itAttr = std::find_if(itAttr, aAttrs.end(), FindByParagraph(nPara));
if (itAttr == aAttrs.end())
@@ -721,14 +721,14 @@ void EditTextObject::GetAllSections( std::vector<editeng::Section>& rAttrs ) con
void EditTextObject::GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& rFamily) const
{
const ContentInfo& rC = *maContents[nPara];
const EditEngineParagraph& rC = *maParagraphs[nPara];
rName = rC.GetStyle();
rFamily = rC.GetFamily();
}
void EditTextObject::SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& rFamily)
{
ContentInfo& rC = *maContents[nPara];
EditEngineParagraph& rC = *maParagraphs[nPara];
rC.SetStyle(rName);
rC.SetFamily(rFamily);
}
@@ -737,12 +737,12 @@ bool EditTextObject::ImpChangeStyleSheets(
std::u16string_view rOldName, SfxStyleFamily eOldFamily,
const OUString& rNewName, SfxStyleFamily eNewFamily )
{
const size_t nParagraphs = maContents.size();
const size_t nParagraphs = maParagraphs.size();
bool bChanges = false;
for (size_t nPara = 0; nPara < nParagraphs; ++nPara)
{
ContentInfo& rC = *maContents[nPara];
EditEngineParagraph& rC = *maParagraphs[nPara];
if ( rC.GetFamily() == eOldFamily )
{
if ( rC.GetStyle() == rOldName )
@@ -792,7 +792,7 @@ bool EditTextObject::Equals( const EditTextObject& rCompare, bool bComparePool )
return false;
return std::equal(
maContents.begin(), maContents.end(), rCompare.maContents.begin(), rCompare.maContents.end(),
maParagraphs.begin(), maParagraphs.end(), rCompare.maParagraphs.begin(), rCompare.maParagraphs.end(),
[bComparePool](const auto& c1, const auto& c2) { return c1->Equals(*c2, bComparePool); });
}
@@ -800,7 +800,7 @@ bool EditTextObject::Equals( const EditTextObject& rCompare, bool bComparePool )
bool EditTextObject::isWrongListEqual(const EditTextObject& rCompare) const
{
return std::equal(
maContents.begin(), maContents.end(), rCompare.maContents.begin(), rCompare.maContents.end(),
maParagraphs.begin(), maParagraphs.end(), rCompare.maParagraphs.begin(), rCompare.maParagraphs.end(),
[](const auto& c1, const auto& c2) { return c1->isWrongListEqual(*c2); });
}
+8 -8
View File
@@ -112,7 +112,7 @@ public:
double getSpacingScaleY() const { return mfSpacingScaleY; }
};
class ContentInfo
class EditEngineParagraph
{
friend class EditTextObject;
@@ -129,13 +129,13 @@ private:
sal_Int16 mnNumberingStartValue { -1 };
bool mbNumberingRestart { false };
ContentInfo( SfxItemPool& rPool );
ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse );
EditEngineParagraph( SfxItemPool& rPool );
EditEngineParagraph( const EditEngineParagraph& rCopyFrom, SfxItemPool& rPoolToUse );
public:
~ContentInfo();
ContentInfo(const ContentInfo&) = delete;
ContentInfo& operator=(const ContentInfo&) = delete;
~EditEngineParagraph();
EditEngineParagraph(const EditEngineParagraph&) = delete;
EditEngineParagraph& operator=(const EditEngineParagraph&) = delete;
void NormalizeString( svl::SharedStringPool& rPool );
const svl::SharedString& GetSharedString() const { return maText;}
@@ -159,10 +159,10 @@ public:
const WrongList* GetWrongList() const;
void SetWrongList( WrongList* p );
bool Equals( const ContentInfo& rCompare, bool bComparePool ) const;
bool Equals( const EditEngineParagraph& rCompare, bool bComparePool ) const;
// #i102062#
bool isWrongListEqual(const ContentInfo& rCompare) const;
bool isWrongListEqual(const EditEngineParagraph& rCompare) const;
sal_Int16 GetNumberingDepth() const { return mnNumberingDepth; }
void SetNumberingDepth(sal_Int16 nDepth) { mnNumberingDepth = nDepth; }
+6 -6
View File
@@ -44,10 +44,10 @@ public:
void updateTableFields(int nTab)
{
SfxItemPool* pPool = mrObj.GetPool();
EditTextObject::ContentInfosType& rContents = mrObj.GetContents();
for (std::unique_ptr<ContentInfo> & i : rContents)
EditTextObject::EditEngineParagraphs& rContents = mrObj.GetParagraphs();
for (std::unique_ptr<EditEngineParagraph> & i : rContents)
{
ContentInfo& rContent = *i;
EditEngineParagraph& rContent = *i;
for (XEditAttribute & rAttr : rContent.GetCharAttribs())
{
const SfxPoolItem* pItem = rAttr.GetItem();
@@ -71,10 +71,10 @@ public:
void UpdatePageRelativeURLs(const std::function<void(const SvxFieldItem & rFieldItem, SvxFieldItemUpdater& rFieldItemUpdater)>& rItemCallback)
{
EditTextObject::ContentInfosType& rContents = mrObj.GetContents();
for (std::unique_ptr<ContentInfo> & i : rContents)
EditTextObject::EditEngineParagraphs& rContents = mrObj.GetParagraphs();
for (std::unique_ptr<EditEngineParagraph> & i : rContents)
{
ContentInfo& rContent = *i;
EditEngineParagraph& rContent = *i;
for (XEditAttribute & rAttr : rContent.GetCharAttribs())
{
const SfxPoolItem* pItem = rAttr.GetItem();
+3 -3
View File
@@ -1227,7 +1227,7 @@ EditTextObject ImpEditEngine::CreateTextObject( EditSelection aSel, SfxItemPool*
nEndPos = aSel.Max().GetIndex();
ContentInfo *pC = aTxtObj.CreateAndInsertContent();
EditEngineParagraph *pC = aTxtObj.CreateAndInsertParagraph();
// The paragraph attributes ...
pC->GetParaAttribs().Set( pNode->GetContentAttribs().GetItems() );
@@ -1393,13 +1393,13 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject
// Before, paragraph count was of type sal_uInt16 so if nContents exceeded
// 0xFFFF this wouldn't have worked anyway, given that nPara is used to
// number paragraphs and is fearlessly incremented.
sal_Int32 nContents = static_cast<sal_Int32>(rTextObject.GetContents().size());
sal_Int32 nContents = static_cast<sal_Int32>(rTextObject.GetParagraphs().size());
SAL_WARN_IF( nContents < 0, "editeng", "ImpEditEngine::InsertTextObject - contents overflow " << nContents);
sal_Int32 nPara = maEditDoc.GetPos( aPaM.GetNode() );
for (sal_Int32 n = 0; n < nContents; ++n, ++nPara)
{
const ContentInfo* pC = rTextObject.GetContents()[n].get();
const EditEngineParagraph* pC = rTextObject.GetParagraphs()[n].get();
bool bNewContent = aPaM.GetNode()->Len() == 0;
const sal_Int32 nStartPos = aPaM.GetIndex();
+5
View File
@@ -112,8 +112,13 @@ SvxFieldData* SvxFieldData::Create(const uno::Reference<text::XTextContent>& xTe
xPropSet->getPropertyValue(UNO_TC_PROP_URL_TARGET) >>= aTarget;
xPropSet->getPropertyValue(UNO_TC_PROP_URL) >>= aURL;
xPropSet->getPropertyValue(UNO_TC_PROP_URL_FORMAT) >>= nFmt;
// Calc's own URL field has no name, and a miss here would drop the field
OUString aName;
if (xPropSet->getPropertySetInfo()->hasPropertyByName(UNO_TC_PROP_NAME))
xPropSet->getPropertyValue(UNO_TC_PROP_NAME) >>= aName;
SvxURLField* pData = new SvxURLField(aURL, aRep, aRep.isEmpty() ? SvxURLFormat::Url : SvxURLFormat::Repr);
pData->SetTargetFrame(aTarget);
pData->SetName(aName);
if (static_cast<SvxURLFormat>(nFmt) >= SvxURLFormat::AppDefault &&
static_cast<SvxURLFormat>(nFmt) <= SvxURLFormat::Repr)
pData->SetFormat(static_cast<SvxURLFormat>(nFmt));
+15 -1
View File
@@ -322,7 +322,8 @@ SvxAdjustItem::SvxAdjustItem(const SvxAdjust eAdjst, const sal_uInt16 nId )
nPropLetterSpacingMaximum(0),
nPropScaleWidthMinimum(100),
nPropScaleWidthMaximum(100),
bParagraphComposer(false)
bParagraphComposer(false),
bCompoundBased(false)
{
SetAdjust( eAdjst );
}
@@ -342,6 +343,7 @@ bool SvxAdjustItem::operator==( const SfxPoolItem& rAttr ) const
bParagraphComposer == rItem.bParagraphComposer &&
nPropLetterSpacingMinimum == rItem.nPropLetterSpacingMinimum &&
nPropLetterSpacingMaximum == rItem.nPropLetterSpacingMaximum &&
bCompoundBased == rItem.bCompoundBased &&
nPropScaleWidthMinimum == rItem.nPropScaleWidthMinimum &&
nPropScaleWidthMaximum == rItem.nPropScaleWidthMaximum;
}
@@ -359,6 +361,7 @@ size_t SvxAdjustItem::hashCode() const
o3tl::hash_combine(seed, bParagraphComposer);
o3tl::hash_combine(seed, nPropLetterSpacingMinimum);
o3tl::hash_combine(seed, nPropLetterSpacingMaximum);
o3tl::hash_combine(seed, bCompoundBased);
o3tl::hash_combine(seed, nPropScaleWidthMinimum);
o3tl::hash_combine(seed, nPropScaleWidthMaximum);
return seed;
@@ -388,6 +391,11 @@ bool SvxAdjustItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
rVal <<= bParagraphComposer;
break;
}
case MID_COMPOUND_BASED :
{
rVal <<= bCompoundBased;
break;
}
default: ;//prevent warning
}
return true;
@@ -471,6 +479,12 @@ bool SvxAdjustItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
bParagraphComposer = Any2Bool(rVal);
}
break;
case MID_COMPOUND_BASED :
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
bCompoundBased = Any2Bool(rVal);
}
break;
case MID_EXPAND_SINGLE :
ASSERT_CHANGE_REFCOUNTED_ITEM;
bOneBlock = Any2Bool(rVal);
+5 -1
View File
@@ -121,7 +121,11 @@ static bool NonFieldWordDelim( const sal_Unicode c )
static bool IsWordDelim( const sal_Unicode c )
{
return c == 0x1 || NonFieldWordDelim(c);
// tdf#154463 - 0x01 ... 0x08 are the characters put into the text to
// anchor a text attribute or to delimit a fieldmark: CH_TXTATR_BREAKWORD,
// CH_TXT_ATR_FIELDSEP, CH_TXT_ATR_INPUTFIELDSTART/END, CH_TXT_ATR_FORMELEMENT
// and CH_TXT_ATR_FIELDSTART/END (see sw/inc/hintids.hxx).
return (0x01 <= c && c <= 0x08) || NonFieldWordDelim(c);
}
+12
View File
@@ -57,6 +57,7 @@ using namespace ::com::sun::star;
#define WID_STRING1 5
#define WID_STRING2 6
#define WID_STRING3 7
#define WID_STRING4 8
class SvxUnoFieldData_Impl
{
@@ -68,6 +69,7 @@ public:
OUString msString1;
OUString msString2;
OUString msString3;
OUString msString4;
util::DateTime maDateTime;
OUString msPresentation;
@@ -96,6 +98,7 @@ static const SfxItemPropertySet* ImplGetFieldItemPropertySet( sal_Int32 mnId )
{ UNO_TC_PROP_URL_REPRESENTATION, WID_STRING1, ::cppu::UnoType<OUString>::get(), 0, 0 },
{ UNO_TC_PROP_URL_TARGET, WID_STRING2, ::cppu::UnoType<OUString>::get(), 0, 0 },
{ UNO_TC_PROP_URL, WID_STRING3, ::cppu::UnoType<OUString>::get(), 0, 0 },
{ UNO_TC_PROP_NAME, WID_STRING4, ::cppu::UnoType<OUString>::get(), 0, 0 },
};
static const SfxItemPropertySet aUrlFieldPropertySet_Impl(aUrlFieldPropertyMap_Impl);
@@ -340,6 +343,7 @@ SvxUnoTextField::SvxUnoTextField( uno::Reference< text::XTextRange > xAnchor, co
mpImpl->msString1 = static_cast<const SvxURLField*>(pData)->GetRepresentation();
mpImpl->msString2 = static_cast<const SvxURLField*>(pData)->GetTargetFrame();
mpImpl->msString3 = static_cast<const SvxURLField*>(pData)->GetURL();
mpImpl->msString4 = static_cast<const SvxURLField*>(pData)->GetName();
mpImpl->mnInt16 = sal::static_int_cast< sal_Int16 >(
static_cast<const SvxURLField*>(pData)->GetFormat());
break;
@@ -426,6 +430,7 @@ std::unique_ptr<SvxFieldData> SvxUnoTextField::CreateFieldData() const noexcept
case text::textfield::Type::URL:
pData.reset( new SvxURLField( mpImpl->msString3, mpImpl->msString1, !mpImpl->msString1.isEmpty() ? SvxURLFormat::Repr : SvxURLFormat::Url ) );
static_cast<SvxURLField*>(pData.get())->SetTargetFrame( mpImpl->msString2 );
static_cast<SvxURLField*>(pData.get())->SetName( mpImpl->msString4 );
if( static_cast<SvxURLFormat>(mpImpl->mnInt16) >= SvxURLFormat::AppDefault &&
static_cast<SvxURLFormat>(mpImpl->mnInt16) <= SvxURLFormat::Repr )
static_cast<SvxURLField*>(pData.get())->SetFormat( static_cast<SvxURLFormat>(mpImpl->mnInt16) );
@@ -722,6 +727,10 @@ void SAL_CALL SvxUnoTextField::setPropertyValue( const OUString& aPropertyName,
if(aValue >>= mpImpl->msString3)
return;
break;
case WID_STRING4:
if(aValue >>= mpImpl->msString4)
return;
break;
}
throw lang::IllegalArgumentException();
@@ -769,6 +778,9 @@ uno::Any SAL_CALL SvxUnoTextField::getPropertyValue( const OUString& PropertyNam
case WID_STRING3:
aValue <<= mpImpl->msString3;
break;
case WID_STRING4:
aValue <<= mpImpl->msString4;
break;
}
return aValue;
+22 -3
View File
@@ -348,6 +348,17 @@ namespace emfio
return Size( nW, nH );
}
// The number of points that fit in a record of nRecordSize words. A record starts with
// three words of header followed by nParameterWords of other parameters, and each point
// takes two words.
static sal_uInt32 MaxPointsInRecord(sal_uInt32 nRecordSize, sal_uInt32 nParameterWords)
{
const sal_uInt32 nUsedWords = 3 + nParameterWords;
if (nRecordSize <= nUsedWords)
return 0;
return (nRecordSize - nUsedWords) / 2;
}
void WmfReader::ReadRecordParams( sal_uInt32 nRecordSize, sal_uInt16 nFunc )
{
bool bRecordOk = true;
@@ -575,7 +586,7 @@ namespace emfio
sal_uInt16 nPoints(0);
mpInputStream->ReadUInt16(nPoints);
if (nPoints > mpInputStream->remainingSize() / (2 * sizeof(sal_uInt16)))
if (nPoints > MaxPointsInRecord(nRecordSize, 1))
{
bRecordOk = false;
}
@@ -600,7 +611,9 @@ namespace emfio
mpInputStream->ReadUInt16( nPolyCount );
if (nPolyCount && mpInputStream->good())
{
if (nPolyCount > mpInputStream->remainingSize() / sizeof(sal_uInt16))
// One word per polygon holds its point count, and those words sit between
// the polygon count and the points themselves.
if (nRecordSize < 4 || nPolyCount > nRecordSize - 4)
break;
// Number of points of each polygon. Determine total number of points
@@ -623,6 +636,12 @@ namespace emfio
SAL_WARN_IF(!bRecordOk, "emfio", "polypolygon record has more polygons than we can handle");
if (nPoints > MaxPointsInRecord(nRecordSize, 1 + nPolyCount))
{
SAL_WARN("emfio", "polypolygon record has more points than it can hold");
bRecordOk = false;
}
bRecordOk &= mpInputStream->good();
if (!bRecordOk)
@@ -665,7 +684,7 @@ namespace emfio
sal_uInt16 nPoints(0);
mpInputStream->ReadUInt16(nPoints);
if (nPoints > mpInputStream->remainingSize() / (2 * sizeof(sal_uInt16)))
if (nPoints > MaxPointsInRecord(nRecordSize, 1))
{
bRecordOk = false;
}
+1
View File
@@ -30,6 +30,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,cairo,\
external/cairo/cairo/avoid-negative-left-shift.patch.1 \
external/cairo/cairo/ubsan-memcpy-nullptr.patch.1 \
external/cairo/cairo/ubsan-memcpy-nullptr2.patch.1 \
external/cairo/cairo/cairo.ofz516227797-Integer-overflow.patch.1 \
external/cairo/cairo/Wincompatible-pointer-types.patch.0 \
external/cairo/cairo/disable-cairo-utilities.patch.1 \
))
@@ -0,0 +1,43 @@
diff -ur cairo.org/src/cairo-spline.c cairo/src/cairo-spline.c
--- cairo.org/src/cairo-spline.c 2026-09-13 14:29:04.468307688 +0000
+++ cairo/src/cairo-spline.c 2026-09-13 14:29:04.482278900 +0000
@@ -141,8 +141,10 @@
static void
_lerp_half (const cairo_point_t *a, const cairo_point_t *b, cairo_point_t *result)
{
- result->x = a->x + ((b->x - a->x) >> 1);
- result->y = a->y + ((b->y - a->y) >> 1);
+ /* The midpoint lies between the two points, so the result fits in a
+ * cairo_fixed_t even when the distance between them does not. */
+ result->x = (cairo_fixed_t) ((int64_t) a->x + (((int64_t) b->x - a->x) >> 1));
+ result->y = (cairo_fixed_t) ((int64_t) a->y + (((int64_t) b->y - a->y) >> 1));
}
static void
@@ -181,11 +183,11 @@
* and c control points and the segment a-b. The maximum of these two
* distances will be our approximation error. */
- bdx = _cairo_fixed_to_double (knots->b.x - knots->a.x);
- bdy = _cairo_fixed_to_double (knots->b.y - knots->a.y);
+ bdx = _cairo_fixed_to_double (knots->b.x) - _cairo_fixed_to_double (knots->a.x);
+ bdy = _cairo_fixed_to_double (knots->b.y) - _cairo_fixed_to_double (knots->a.y);
- cdx = _cairo_fixed_to_double (knots->c.x - knots->a.x);
- cdy = _cairo_fixed_to_double (knots->c.y - knots->a.y);
+ cdx = _cairo_fixed_to_double (knots->c.x) - _cairo_fixed_to_double (knots->a.x);
+ cdy = _cairo_fixed_to_double (knots->c.y) - _cairo_fixed_to_double (knots->a.y);
if (knots->a.x != knots->d.x || knots->a.y != knots->d.y) {
/* Intersection point (px):
@@ -197,8 +199,8 @@
double dx, dy, u, v;
- dx = _cairo_fixed_to_double (knots->d.x - knots->a.x);
- dy = _cairo_fixed_to_double (knots->d.y - knots->a.y);
+ dx = _cairo_fixed_to_double (knots->d.x) - _cairo_fixed_to_double (knots->a.x);
+ dy = _cairo_fixed_to_double (knots->d.y) - _cairo_fixed_to_double (knots->a.y);
v = dx * dx + dy * dy;
u = bdx * dx + bdy * dy;
+2 -2
View File
@@ -16,11 +16,11 @@ $(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/ifbclient.
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/Engine12.dll,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/plugins/Engine12.dll))
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/intl/fbintl.dll,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/intl/fbintl.dll))
else ifeq ($(OS),MACOSX)
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/libfbclient.dylib.3.0.13,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/lib/libfbclient.dylib.3.0.13))
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/libfbclient.dylib.3.0.14,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/lib/libfbclient.dylib.3.0.14))
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/libEngine12.dylib,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/plugins/libEngine12.dylib))
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/intl/libfbintl.dylib,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/intl/libfbintl.dylib))
else ifeq ($(DISABLE_DYNLOADING),)
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/libfbclient.so.2,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/lib/libfbclient.so.3.0.13))
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/libfbclient.so.2,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/lib/libfbclient.so.3.0.14))
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/libEngine12.so,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/plugins/libEngine12.so))
$(eval $(call gb_ExternalPackage_add_file,firebird,$(LIBO_LIB_FOLDER)/intl/libfbintl.so,gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird/intl/libfbintl.so))
endif
+1 -1
View File
@@ -23,7 +23,7 @@ $(eval $(call gb_ExternalProject_register_targets,firebird,\
))
firebird_BUILDDIR = $(EXTERNAL_WORKDIR)/gen/$(if $(ENABLE_DEBUG),Debug,Release)/firebird
firebird_VERSION := 3.0.13
firebird_VERSION := 3.0.14
$(call gb_ExternalProject_get_state_target,firebird,build):
$(call gb_Trace_StartRange,firebird,EXTERNAL)
-1
View File
@@ -47,7 +47,6 @@ $(eval $(call gb_UnpackedTarball_add_patches,firebird,\
external/firebird/0001-extern-cloop-Missing-dependency-of-BIN_DIR-cloop-on-.patch.1 \
external/firebird/msvc.patch \
external/firebird/wnt-per-process-trace-storage.patch.1 \
external/firebird/configure-c99.patch \
external/firebird/Wincompatible-function-pointer-types.patch \
external/firebird/0001-Revert-Backported-fix-for-7122-Invalid-state-of-mapp.patch.1 \
external/firebird/0001-Revert-Fix-for-most-cases-of-7522-7828.patch.1 \
-45
View File
@@ -1,45 +0,0 @@
--- configure
+++ configure
@@ -20687,8 +20687,9 @@
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
+#include <stdlib.h>
#include <semaphore.h>
- main () {
+ int main () {
sem_t s;
return sem_init(&s,0,0);
}
@@ -21432,8 +21433,9 @@
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
+#include <stdlib.h>
#include <unistd.h>
- main () {
+ int main () {
return !(sizeof(off_t) == 8);
}
_ACEOF
@@ -21647,8 +21649,9 @@
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
+#include <stdlib.h>
#include <semaphore.h>
-main () {
+int main () {
struct s {
char a;
union { long long x; sem_t y; } b;
@@ -21683,7 +21686,8 @@
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-main () {
+#include <stdlib.h>
+int main () {
struct s {
char a;
double b;
+2 -2
View File
@@ -29,10 +29,10 @@
--- configure 2023-11-11 02:44:14.576802800 +0900
+++ configure 2023-11-11 02:59:09.005211200 +0900
@@ -21650,11 +21650,10 @@
@@ -21674,11 +21674,10 @@
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
-#include <semaphore.h>
int main () {
struct s {
+1
View File
@@ -33,6 +33,7 @@ $(eval $(call gb_StaticLibrary_add_generated_exception_objects,hunspell,\
UnpackedTarball/hunspell/src/hunspell/hashmgr \
UnpackedTarball/hunspell/src/hunspell/suggestmgr \
UnpackedTarball/hunspell/src/hunspell/phonet \
UnpackedTarball/hunspell/src/hunspell/hunspelltrace \
UnpackedTarball/hunspell/src/hunspell/hunzip \
UnpackedTarball/hunspell/src/hunspell/filemgr \
UnpackedTarball/hunspell/src/hunspell/replist \
+2 -2
View File
@@ -16,9 +16,9 @@ ifeq ($(OS),MACOSX)
$(eval $(call gb_ExternalPackage_add_file,libxml2,$(LIBO_URE_LIB_FOLDER)/libxml2.16.dylib,.libs/libxml2.16.dylib))
else ifeq ($(OS),WNT)
ifeq ($(COM),GCC)
$(eval $(call gb_ExternalPackage_add_file,libxml2,$(LIBO_URE_LIB_FOLDER)/libxml2$(if $(MSVC_USE_DEBUG_RUNTIME),d).dll,$(if $(MSVC_USE_DEBUG_RUNTIME),Debug,Release)/libxml2$(if $(MSVC_USE_DEBUG_RUNTIME),d).dll))
$(eval $(call gb_ExternalPackage_add_file,libxml2,$(LIBO_URE_LIB_FOLDER)/libxml2$(if $(MSVC_USE_DEBUG_RUNTIME),d).dll,libxml2$(if $(MSVC_USE_DEBUG_RUNTIME),d).dll))
else # COM=MSC
$(eval $(call gb_ExternalPackage_add_file,libxml2,$(LIBO_URE_LIB_FOLDER)/libxml2$(if $(MSVC_USE_DEBUG_RUNTIME),d).dll,$(if $(MSVC_USE_DEBUG_RUNTIME),Debug,Release)/libxml2$(if $(MSVC_USE_DEBUG_RUNTIME),d).dll))
$(eval $(call gb_ExternalPackage_add_file,libxml2,$(LIBO_URE_LIB_FOLDER)/libxml2$(if $(MSVC_USE_DEBUG_RUNTIME),d).dll,libxml2$(if $(MSVC_USE_DEBUG_RUNTIME),d).dll))
endif
else # OS!=WNT
$(eval $(call gb_ExternalPackage_add_file,libxml2,$(LIBO_URE_LIB_FOLDER)/libxml2.so.16,.libs/libxml2.so.16.1.$(LIBXML_VERSION_MICRO)))
+10 -6
View File
@@ -25,11 +25,15 @@ $(call gb_ExternalProject_use_external_project,libxml2,icu)
# workdir\UnpackedTarball\libxml2\version(1): error C2059: syntax error: 'constant
$(call gb_ExternalProject_get_state_target,libxml2,build):
$(call gb_Trace_StartRange,libxml2,EXTERNAL)
$(call gb_ExternalProject_run,build,\
$(CMAKE) . \
$(if $(filter 17.%,$(VCVER)),-G "Visual Studio 17 2022") \
$(if $(filter 18.%,$(VCVER)),-G "Visual Studio 18 2026") \
-A $(gb_MSBUILD_PLATFORM) \
+$(call gb_ExternalProject_run,build,\
export INCLUDE="$(gb_ExternalProject_INCLUDE)" \
&& export LIB="$(ILIB)" \
&& $(CMAKE) . \
-G Ninja \
-DCMAKE_MAKE_PROGRAM=$(NINJA) \
-DCMAKE_BUILD_TYPE=$(if $(MSVC_USE_DEBUG_RUNTIME),Debug,Release) \
-DCMAKE_C_COMPILER=$(lastword $(filter-out -%,$(CC))) \
$(if $(CCACHE),-DCMAKE_C_COMPILER_LAUNCHER=$(CCACHE)) \
-DLIBXML2_WITH_TESTS=OFF \
-DLIBXML2_WITH_ICONV=OFF \
-DLIBXML2_WITH_PYTHON=OFF \
@@ -40,7 +44,7 @@ $(call gb_ExternalProject_get_state_target,libxml2,build):
$(if $(MSVC_USE_DEBUG_RUNTIME), \
-DICU_UC_LIBRARY_DEBUG=$(gb_UnpackedTarball_workdir)/icu/source/lib/icuucd.lib, \
-DICU_UC_LIBRARY_RELEASE=$(gb_UnpackedTarball_workdir)/icu/source/lib/icuuc.lib) \
&& $(CMAKE) --build . --config $(if $(MSVC_USE_DEBUG_RUNTIME),Debug,Release) \
&& $(CMAKE) --build . \
&& rm VERSION \
)
$(call gb_Trace_EndRange,libxml2,EXTERNAL)
+1 -1
View File
@@ -24,7 +24,7 @@ $(call gb_ExternalProject_get_state_target,libxslt,build):
$(if $(MSVC_USE_DEBUG_RUNTIME),cruntime=/MDd) \
$(if $(filter TRUE,$(ENABLE_DBGUTIL)),debug=yes) \
vcmanifest=yes \
lib=$(gb_UnpackedTarball_workdir)/libxml2/$(if $(MSVC_USE_DEBUG_RUNTIME),Debug,Release) \
lib=$(gb_UnpackedTarball_workdir)/libxml2 \
&& nmake \
,win32)
$(call gb_Trace_EndRange,libxslt,EXTERNAL)
-17
View File
@@ -1,17 +0,0 @@
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# 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/.
#
$(eval $(call gb_ExternalPackage_ExternalPackage,fonts_scheherazade,font_scheherazade))
$(eval $(call gb_ExternalPackage_add_unpacked_files,fonts_scheherazade,$(LIBO_SHARE_FOLDER)/fonts/truetype,\
Scheherazade-Bold.ttf \
Scheherazade-Regular.ttf \
))
# vim: set noet sw=4 ts=4:
-2
View File
@@ -35,7 +35,6 @@ $(eval $(call gb_Module_add_targets,more_fonts,\
ExternalPackage_noto_serif_hebrew \
ExternalPackage_noto_serif_lao \
ExternalPackage_reem \
ExternalPackage_scheherazade \
UnpackedTarball_alef \
UnpackedTarball_amiri \
UnpackedTarball_caladea \
@@ -61,7 +60,6 @@ $(eval $(call gb_Module_add_targets,more_fonts,\
UnpackedTarball_noto_serif_hebrew \
UnpackedTarball_noto_serif_lao \
UnpackedTarball_reem \
UnpackedTarball_scheherazade \
))
# vim: set noet sw=4 ts=4:
-14
View File
@@ -1,14 +0,0 @@
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# 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/.
#
$(eval $(call gb_UnpackedTarball_UnpackedTarball,font_scheherazade))
$(eval $(call gb_UnpackedTarball_set_tarball,font_scheherazade,$(FONT_SCHEHERAZADE_TARBALL)))
# vim: set noet sw=4 ts=4:
+2
View File
@@ -44,6 +44,7 @@ $(call gb_ExternalProject_get_state_target,nss,build): \
NSINSTALL='$(call gb_ExternalExecutable_get_command,python) $(SRCDIR)/external/nss/nsinstall.py' \
NSS_DISABLE_GTESTS=1 \
NSS_DISABLE_CMD_TOOLS=1 \
NSS_DISABLE_NSPR_TESTS=1 \
CCC="$(CXX)" \
,nss)
$(call gb_Trace_EndRange,nss,EXTERNAL)
@@ -82,6 +83,7 @@ $(call gb_ExternalProject_get_state_target,nss,build): \
$(if $(filter ANDROID,$(OS)),OS_TARGET=Android OS_TARGET_RELEASE=$(ANDROID_API_LEVEL) ARCHFLAG="" DEFAULT_COMPILER=clang ANDROID_NDK=$(ANDROID_NDK_DIR) ANDROID_TOOLCHAIN_VERSION=obsolete ANDROID_PREFIX=$(HOST_PLATFORM) ANDROID_SYSROOT=$(ANDROID_NDK_DIR)/sysroot) \
NSS_DISABLE_GTESTS=1 \
NSS_DISABLE_CMD_TOOLS=1 \
NSS_DISABLE_NSPR_TESTS=1 \
nss_build_all \
&& rm -f $(gb_UnpackedTarball_workdir)/nss/dist/out/lib/*.a \
$(if $(filter MACOSX,$(OS)),\
-8
View File
@@ -50,14 +50,6 @@ diff -ur nss.org/nss/Makefile nss/nss/Makefile
--with-android-version=$(OS_TARGET_RELEASE) \
--with-android-toolchain=$(ANDROID_TOOLCHAIN) \
--with-android-platform=$(ANDROID_SYSROOT)
@@ -143,7 +143,6 @@
ifndef NSS_DISABLE_NSPR_TESTS
build_nspr: $(NSPR_CONFIG_STATUS)
$(MAKE) -C $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)
- $(MAKE) -C $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)/pr/tests
else
build_nspr: $(NSPR_CONFIG_STATUS)
$(MAKE) -C $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)
--- nss/nss/lib/ckfw/builtins/manifest.mn.orig 2019-11-26 15:18:22.185985193 +0100
+++ nss/nss/lib/ckfw/builtins/manifest.mn 2019-11-26 15:18:29.281982387 +0100
@@ -5,7 +5,7 @@
-8
View File
@@ -16,14 +16,6 @@
endif
#
@@ -141,7 +143,6 @@
ifndef NSS_DISABLE_NSPR_TESTS
build_nspr: $(NSPR_CONFIG_STATUS)
$(MAKE) -C $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)
- $(MAKE) -C $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)/pr/tests
else
build_nspr: $(NSPR_CONFIG_STATUS)
$(MAKE) -C $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)
--- a/a/nss/lib/ckfw/builtins/manifest.mn
+++ a/a/nss/lib/ckfw/builtins/manifest.mn
@@ -5,7 +5,7 @@
+5 -5
View File
@@ -1,10 +1,10 @@
--- nss/coreconf/WINNT.mk 2025-03-24 14:11:13.771104127 +0100
+++ nss/coreconf/WINNT.mk 2025-03-24 14:11:13.771104127 +0100
@@ -15,6 +15,3 @@
# Win NT needs -GT so that fibers can work
@@ -8,6 +8,3 @@
#
OS_CFLAGS += -GT
include $(CORE_DEPTH)/coreconf/WIN32.mk
-
-# WINNT uses the lib prefix, Win95 doesn't
-NSPR31_LIB_PREFIX = lib
-# NSPR's WIN95 target prefixes its import libraries only for GCC, like ours.
-NSPR31_LIB_PREFIX = $(IMPORT_LIB_PREFIX)
+4 -1
View File
@@ -32,7 +32,10 @@ endif
# TODO, attempt upstream
pdfium_patches += ofz451333752.patch
pdfium_patches += extractpatterns.patch
# https://pdfium-review.googlesource.com/c/pdfium/+/154910
pdfium_patches += extractpatterns-stroke.patch.1
# https://pdfium-review.googlesource.com/c/pdfium/+/157490
pdfium_patches += extractpatterns-fill.patch.1
pdfium_patches += charbboxinflation.patch.1
# Hide bundled FreeType symbols
pdfium_patches += freetype-hidden-visibility.patch
+179
View File
@@ -0,0 +1,179 @@
From 3e9b2c24c3c35c17ad887f6b415e04163d97ae3c Mon Sep 17 00:00:00 2001
Date: Thu, 17 Sep 2026 15:52:06 -0700
Subject: [PATCH] Add FPDFPageObj_GetRenderedFillPattern() API
This is similar to http://pdfium-review.googlesource.com/c/154910, but
that one was for stroke patterns and this is for fill patterns.
Change-Id: I9929e232472fdd974009c64bcb1109d69a813d0a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/157490
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
---
fpdfsdk/fpdf_edit_embeddertest.cpp | 64 ++++++++++++++
fpdfsdk/fpdf_editpage.cpp | 79 +++++++++++-------
fpdfsdk/fpdf_view_c_api_test.c | 1 +
public/fpdf_edit.h | 16 ++++
.../resources/embedder_tests/pattern_fill.png | Bin 0 -> 107 bytes
.../embedder_tests/pattern_fill_uncolored.png | Bin 0 -> 107 bytes
testing/resources/pattern_fill.in | 56 +++++++++++++
testing/resources/pattern_fill.pdf | 68 +++++++++++++++
testing/resources/pattern_fill_uncolored.in | 58 +++++++++++++
testing/resources/pattern_fill_uncolored.pdf | 70 ++++++++++++++++
10 files changed, 384 insertions(+), 28 deletions(-)
create mode 100644 testing/resources/embedder_tests/pattern_fill.png
create mode 100644 testing/resources/embedder_tests/pattern_fill_uncolored.png
create mode 100644 testing/resources/pattern_fill.in
create mode 100644 testing/resources/pattern_fill.pdf
create mode 100644 testing/resources/pattern_fill_uncolored.in
create mode 100644 testing/resources/pattern_fill_uncolored.pdf
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index 9b9474ed7..033572048 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -199,7 +199,8 @@ ByteString FormatPDFDate(time_t current_time, const tm& local_time) {
FPDF_BITMAP RenderTilingPatternToBitmap(CPDF_Pattern* pattern,
CPDF_Document* doc,
- CPDF_PageObject* page_obj) {
+ CPDF_PageObject* page_obj,
+ bool use_stroke_color) {
CPDF_TilingPattern* tiling_pattern = pattern->AsTilingPattern();
if (!tiling_pattern) {
return nullptr;
@@ -228,10 +229,13 @@ FPDF_BITMAP RenderTilingPatternToBitmap(CPDF_Pattern* pattern,
return FPDFBitmapFromCFXDIBitmap(cell_bitmap.Leak());
}
- // An uncolored pattern gets its color from the stroke color operands.
- const FX_COLORREF stroke_colorref =
- page_obj->color_state().GetStrokeColorRef();
- if (stroke_colorref == 0xFFFFFFFF) {
+ // An uncolored pattern gets its color from the stroke/fill color operands.
+ const CPDF_ColorState& color_state = page_obj->color_state();
+ const FX_COLORREF colorref =
+ use_stroke_color ? color_state.GetStrokeColorRef()
+ : color_state.GetFillColorRef();
+ // 0xFFFFFFFF is the unusable color, see FX_COLORREF.
+ if (colorref == 0xFFFFFFFF) {
return nullptr;
}
@@ -240,11 +244,14 @@ FPDF_BITMAP RenderTilingPatternToBitmap(CPDF_Pattern* pattern,
FXDIB_Format::kBgra)) {
return nullptr;
}
- const int stroke_alpha =
- static_cast<int>(page_obj->general_state().GetStrokeAlpha() * 255);
+ const CPDF_GeneralState& general_state = page_obj->general_state();
+ const float float_alpha = use_stroke_color
+ ? general_state.GetStrokeAlpha()
+ : general_state.GetFillAlpha();
+ const int alpha = static_cast<int>(float_alpha * 255);
if (!result_bitmap->CompositeMask(
/*dest_left=*/0, /*dest_top=*/0, rect.Width(), rect.Height(),
- cell_bitmap, AlphaAndColorRefToArgb(stroke_alpha, stroke_colorref),
+ cell_bitmap, AlphaAndColorRefToArgb(alpha, colorref),
/*src_left=*/0, /*src_top=*/0, BlendMode::kNormal)) {
return nullptr;
}
@@ -255,6 +262,36 @@ FPDF_BITMAP RenderTilingPatternToBitmap(CPDF_Pattern* pattern,
return FPDFBitmapFromCFXDIBitmap(result_bitmap.Leak());
}
+FPDF_BITMAP GetRenderedPattern(FPDF_DOCUMENT document,
+ FPDF_PAGEOBJECT page_object,
+ bool use_stroke_color) {
+ CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
+ if (!doc) {
+ return nullptr;
+ }
+
+ CPDF_PageObject* object = CPDFPageObjectFromFPDFPageObject(page_object);
+ if (!object) {
+ return nullptr;
+ }
+
+ const CPDF_ColorState& color_state = object->color_state();
+ const CPDF_Color* color = use_stroke_color
+ ? color_state.GetStrokeColor()
+ : color_state.GetFillColor();
+ if (!color || !color->IsPattern()) {
+ return nullptr;
+ }
+
+ RetainPtr<CPDF_Pattern> pattern = color->GetPattern();
+ if (!pattern) {
+ return nullptr;
+ }
+
+ return RenderTilingPatternToBitmap(pattern.Get(), doc, object,
+ use_stroke_color);
+}
+
} // namespace
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_CreateNewDocument() {
@@ -1261,27 +1298,13 @@ FPDFPageObj_SetDashArray(FPDF_PAGEOBJECT page_object,
FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
FPDFPageObj_GetRenderedStrokePattern(FPDF_DOCUMENT document,
FPDF_PAGEOBJECT page_object) {
- CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
- if (!doc) {
- return nullptr;
- }
-
- CPDF_PageObject* object = CPDFPageObjectFromFPDFPageObject(page_object);
- if (!object) {
- return nullptr;
- }
-
- const CPDF_Color* stroke = object->color_state().GetStrokeColor();
- if (!stroke || !stroke->IsPattern()) {
- return nullptr;
- }
-
- RetainPtr<CPDF_Pattern> pattern = stroke->GetPattern();
- if (!pattern) {
- return nullptr;
- }
+ return GetRenderedPattern(document, page_object, /*use_stroke_color=*/true);
+}
- return RenderTilingPatternToBitmap(pattern.Get(), doc, object);
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
+FPDFPageObj_GetRenderedFillPattern(FPDF_DOCUMENT document,
+ FPDF_PAGEOBJECT page_object) {
+ return GetRenderedPattern(document, page_object, /*use_stroke_color=*/false);
}
FPDF_EXPORT int FPDF_CALLCONV
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index c7fca05a1..77fa19c81 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -1206,6 +1206,22 @@ FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
FPDFPageObj_GetRenderedStrokePattern(FPDF_DOCUMENT document,
FPDF_PAGEOBJECT page_object);
+// Experimental API.
+// Get a bitmap rasterization of the fill pattern of |page_object|.
+// To render correctly, the caller must provide the |document| associated with
+// |page_object|. The returned bitmap will be owned by the caller, and
+// FPDFBitmap_Destroy() must be called on the returned bitmap when it is no
+// longer needed.
+//
+// document - handle to the document containing |page_object|.
+// page_object - handle to a page object.
+//
+// Returns the bitmap, or NULL if the fill is not a tiling pattern or on
+// failure.
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
+FPDFPageObj_GetRenderedFillPattern(FPDF_DOCUMENT document,
+ FPDF_PAGEOBJECT page_object);
+
// Get number of segments inside |path|.
//
// path - handle to a path.
+262
View File
@@ -0,0 +1,262 @@
From 7bf42f401237d9096d44f7508beca8690031a98d Mon Sep 17 00:00:00 2001
Date: Tue, 8 Sep 2026 16:54:21 -0700
Subject: [PATCH] Add FPDFPageObj_GetRenderedStrokePattern() API
This allows getting the rendered bitmap of a stroke pattern of a page
object.
Change-Id: I4603be175bfe8721d4e11500afcc2be8c2c9f760
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/154910
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
---
core/fpdfapi/render/cpdf_rendertiling.cpp | 21 +++--
core/fpdfapi/render/cpdf_rendertiling.h | 14 +++
fpdfsdk/fpdf_edit_embeddertest.cpp | 64 +++++++++++++
fpdfsdk/fpdf_editpage.cpp | 88 ++++++++++++++++++
fpdfsdk/fpdf_view_c_api_test.c | 1 +
public/fpdf_edit.h | 16 ++++
.../embedder_tests/pattern_stroke.png | Bin 0 -> 86 bytes
.../pattern_stroke_uncolored.png | Bin 0 -> 86 bytes
testing/resources/pattern_stroke.in | 59 ++++++++++++
testing/resources/pattern_stroke.pdf | 71 ++++++++++++++
testing/resources/pattern_stroke_uncolored.in | 61 ++++++++++++
.../resources/pattern_stroke_uncolored.pdf | 73 +++++++++++++++
12 files changed, 458 insertions(+), 10 deletions(-)
create mode 100644 testing/resources/embedder_tests/pattern_stroke.png
create mode 100644 testing/resources/embedder_tests/pattern_stroke_uncolored.png
create mode 100644 testing/resources/pattern_stroke.in
create mode 100644 testing/resources/pattern_stroke.pdf
create mode 100644 testing/resources/pattern_stroke_uncolored.in
create mode 100644 testing/resources/pattern_stroke_uncolored.pdf
diff --git a/core/fpdfapi/render/cpdf_rendertiling.cpp b/core/fpdfapi/render/cpdf_rendertiling.cpp
index f407f2403..77027354b 100644
--- a/core/fpdfapi/render/cpdf_rendertiling.cpp
+++ b/core/fpdfapi/render/cpdf_rendertiling.cpp
@@ -26,7 +26,17 @@
namespace {
-RetainPtr<CFX_DIBitmap> DrawPatternBitmap(
+std::optional<int> CheckedFloatToInt(float value) {
+ if (!pdfium::IsValueInRangeForNumericType<int>(value)) {
+ return std::nullopt;
+ }
+ return static_cast<int>(value);
+}
+
+} // namespace
+
+// static
+RetainPtr<CFX_DIBitmap> CPDF_RenderTiling::DrawPatternBitmap(
CPDF_Document* doc,
CPDF_PageImageCache* pCache,
CPDF_TilingPattern* pPattern,
@@ -72,15 +82,6 @@ RetainPtr<CFX_DIBitmap> DrawPatternBitmap(
return pBitmap;
}
-std::optional<int> CheckedFloatToInt(float value) {
- if (!pdfium::IsValueInRangeForNumericType<int>(value)) {
- return std::nullopt;
- }
- return static_cast<int>(value);
-}
-
-} // namespace
-
// static
RetainPtr<CFX_DIBitmap> CPDF_RenderTiling::Draw(
CPDF_RenderStatus* pRenderStatus,
diff --git a/core/fpdfapi/render/cpdf_rendertiling.h b/core/fpdfapi/render/cpdf_rendertiling.h
index 34fb56bf4..2a124461c 100644
--- a/core/fpdfapi/render/cpdf_rendertiling.h
+++ b/core/fpdfapi/render/cpdf_rendertiling.h
@@ -7,11 +7,14 @@
#ifndef CORE_FPDFAPI_RENDER_CPDF_RENDERTILING_H_
#define CORE_FPDFAPI_RENDER_CPDF_RENDERTILING_H_
+#include "core/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fxcrt/retain_ptr.h"
class CFX_DIBitmap;
class CFX_Matrix;
+class CPDF_Document;
class CPDF_Form;
+class CPDF_PageImageCache;
class CPDF_PageObject;
class CPDF_RenderStatus;
class CPDF_TilingPattern;
@@ -27,6 +30,17 @@ class CPDF_RenderTiling {
const FX_RECT& clip_box,
bool bStroke);
+ // Renders a single cell of pPattern into a width x height bitmap.
+ static RetainPtr<CFX_DIBitmap> DrawPatternBitmap(
+ CPDF_Document* doc,
+ CPDF_PageImageCache* pCache,
+ CPDF_TilingPattern* pPattern,
+ CPDF_Form* pPatternForm,
+ const CFX_Matrix& mtObject2Device,
+ int width,
+ int height,
+ const CPDF_RenderOptions::Options& draw_options);
+
CPDF_RenderTiling() = delete;
CPDF_RenderTiling(const CPDF_RenderTiling&) = delete;
CPDF_RenderTiling& operator=(const CPDF_RenderTiling&) = delete;
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index 758aae859..9b9474ed7 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -25,12 +25,15 @@
#include "core/fpdfapi/page/cpdf_pathobject.h"
#include "core/fpdfapi/page/cpdf_shadingobject.h"
#include "core/fpdfapi/page/cpdf_textobject.h"
+#include "core/fpdfapi/page/cpdf_tilingpattern.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fpdfapi/render/cpdf_docrenderdata.h"
+#include "core/fpdfapi/render/cpdf_renderoptions.h"
+#include "core/fpdfapi/render/cpdf_rendertiling.h"
#include "core/fpdfdoc/cpdf_annot.h"
#include "core/fpdfdoc/cpdf_annotlist.h"
#include "core/fxcrt/compiler_specific.h"
@@ -42,6 +45,7 @@
#include "core/fxcrt/span_util.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "public/fpdf_formfill.h"
@@ -193,6 +197,64 @@ ByteString FormatPDFDate(time_t current_time, const tm& local_time) {
return date;
}
+FPDF_BITMAP RenderTilingPatternToBitmap(CPDF_Pattern* pattern,
+ CPDF_Document* doc,
+ CPDF_PageObject* page_obj) {
+ CPDF_TilingPattern* tiling_pattern = pattern->AsTilingPattern();
+ if (!tiling_pattern) {
+ return nullptr;
+ }
+ const std::unique_ptr<CPDF_Form> pattern_form =
+ tiling_pattern->Load(page_obj);
+ if (!pattern_form) {
+ return nullptr;
+ }
+ const FX_RECT rect = tiling_pattern->bbox().GetOuterRect();
+ if (rect.IsEmpty() || !rect.Valid()) {
+ return nullptr;
+ }
+
+ RetainPtr<CFX_DIBitmap> cell_bitmap = CPDF_RenderTiling::DrawPatternBitmap(
+ doc, /*pCache=*/nullptr, tiling_pattern, pattern_form.get(), CFX_Matrix(),
+ rect.Width(), rect.Height(), CPDF_RenderOptions::Options());
+ if (!cell_bitmap) {
+ return nullptr;
+ }
+
+ if (tiling_pattern->colored()) {
+ ValidateBitmapPremultiplyState(cell_bitmap);
+
+ // Caller takes ownership.
+ return FPDFBitmapFromCFXDIBitmap(cell_bitmap.Leak());
+ }
+
+ // An uncolored pattern gets its color from the stroke color operands.
+ const FX_COLORREF stroke_colorref =
+ page_obj->color_state().GetStrokeColorRef();
+ if (stroke_colorref == 0xFFFFFFFF) {
+ return nullptr;
+ }
+
+ auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
+ if (!result_bitmap->Create(rect.Width(), rect.Height(),
+ FXDIB_Format::kBgra)) {
+ return nullptr;
+ }
+ const int stroke_alpha =
+ static_cast<int>(page_obj->general_state().GetStrokeAlpha() * 255);
+ if (!result_bitmap->CompositeMask(
+ /*dest_left=*/0, /*dest_top=*/0, rect.Width(), rect.Height(),
+ cell_bitmap, AlphaAndColorRefToArgb(stroke_alpha, stroke_colorref),
+ /*src_left=*/0, /*src_top=*/0, BlendMode::kNormal)) {
+ return nullptr;
+ }
+
+ ValidateBitmapPremultiplyState(result_bitmap);
+
+ // Caller takes ownership.
+ return FPDFBitmapFromCFXDIBitmap(result_bitmap.Leak());
+}
+
} // namespace
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_CreateNewDocument() {
@@ -1196,6 +1258,32 @@ FPDFPageObj_SetDashArray(FPDF_PAGEOBJECT page_object,
return true;
}
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
+FPDFPageObj_GetRenderedStrokePattern(FPDF_DOCUMENT document,
+ FPDF_PAGEOBJECT page_object) {
+ CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
+ if (!doc) {
+ return nullptr;
+ }
+
+ CPDF_PageObject* object = CPDFPageObjectFromFPDFPageObject(page_object);
+ if (!object) {
+ return nullptr;
+ }
+
+ const CPDF_Color* stroke = object->color_state().GetStrokeColor();
+ if (!stroke || !stroke->IsPattern()) {
+ return nullptr;
+ }
+
+ RetainPtr<CPDF_Pattern> pattern = stroke->GetPattern();
+ if (!pattern) {
+ return nullptr;
+ }
+
+ return RenderTilingPatternToBitmap(pattern.Get(), doc, object);
+}
+
FPDF_EXPORT int FPDF_CALLCONV
FPDFFormObj_CountObjects(FPDF_PAGEOBJECT form_object) {
const auto* pObjectList = CPDFPageObjHolderFromFPDFFormObject(form_object);
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index 8fac863f6..34be3867d 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -1190,6 +1190,22 @@ FPDFPageObj_SetDashArray(FPDF_PAGEOBJECT page_object,
size_t dash_count,
float phase);
+// Experimental API.
+// Get a bitmap rasterization of the stroke pattern of |page_object|.
+// To render correctly, the caller must provide the |document| associated with
+// |page_object|. The returned bitmap will be owned by the caller, and
+// FPDFBitmap_Destroy() must be called on the returned bitmap when it is no
+// longer needed.
+//
+// document - handle to the document containing |page_object|.
+// page_object - handle to a page object.
+//
+// Returns the bitmap, or NULL if the stroke is not a tiling pattern or on
+// failure.
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
+FPDFPageObj_GetRenderedStrokePattern(FPDF_DOCUMENT document,
+ FPDF_PAGEOBJECT page_object);
+
// Get number of segments inside |path|.
//
// path - handle to a path.
-185
View File
@@ -1,185 +0,0 @@
--- core/fpdfapi/page/cpdf_pattern.h 2025-10-17 15:44:08.393532043 +0100
+++ core/fpdfapi/page/cpdf_pattern.h 2025-10-17 15:44:12.020459390 +0100
@@ -26,6 +26,7 @@
virtual CPDF_ShadingPattern* AsShadingPattern();
const CFX_Matrix& pattern_to_form() const { return pattern_to_form_; }
+ RetainPtr<CPDF_Object> pattern_obj() const { return pattern_obj_; }
protected:
CPDF_Pattern(CPDF_Document* doc,
@@ -35,7 +36,6 @@
// All the getters that return pointers return non-NULL pointers.
CPDF_Document* document() const { return document_; }
- RetainPtr<CPDF_Object> pattern_obj() const { return pattern_obj_; }
const CFX_Matrix& parent_matrix() const { return parent_matrix_; }
void SetPatternToFormMatrix();
--- fpdfsdk/fpdf_edittext.cpp 2025-10-17 15:44:08.410532151 +0100
+++ fpdfsdk/fpdf_edittext.cpp 2025-10-17 15:55:18.804847559 +0100
@@ -13,6 +13,9 @@
#include "core/fpdfapi/font/cpdf_cidfont.h"
#include "core/fpdfapi/font/cpdf_font.h"
#include "core/fpdfapi/page/cpdf_docpagedata.h"
+#include "core/fpdfapi/page/cpdf_form.h"
+#include "core/fpdfapi/page/cpdf_pathobject.h"
+#include "core/fpdfapi/page/cpdf_tilingpattern.h"
#include "core/fpdfapi/page/cpdf_textobject.h"
#include "core/fpdfapi/page/cpdf_textstate.h"
#include "core/fpdfapi/parser/cpdf_array.h"
@@ -834,6 +835,110 @@
return FPDFBitmapFromCFXDIBitmap(result_bitmap.Leak());
}
+FPDF_BITMAP
+FPDFPageObj_GetRenderedPattern(CPDF_Pattern& pattern,
+ CPDF_Document& doc,
+ CPDF_PageObject& pageObj,
+ CPDF_Page* optional_page) {
+ CPDF_TilingPattern* pTilingPattern = pattern.AsTilingPattern();
+ if (!pTilingPattern)
+ return nullptr;
+ const std::unique_ptr<CPDF_Form> pPatternForm = pTilingPattern->Load(&pageObj);
+ if (!pPatternForm)
+ return nullptr;
+ RetainPtr<const CPDF_Dictionary> pDict = pattern.pattern_obj()->GetDict();
+ CFX_FloatRect pattern_bbox = pDict->GetRectFor("BBox");
+
+ // `rect` has to use integer values. Round up as needed.
+ const FX_RECT rect = pattern_bbox.GetOuterRect();
+ if (rect.IsEmpty() || !rect.Valid())
+ return nullptr;
+
+ auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
+ if (!result_bitmap->Create(rect.Width(), rect.Height(),
+ FXDIB_Format::kBgra)) {
+ return nullptr;
+ }
+ CFX_FloatRect cell_bbox = pattern.pattern_to_form().TransformRect(pattern_bbox);
+ CFX_FloatRect bitmap_rect(0.0f, 0.0f, rect.Width(), rect.Height());
+ CFX_Matrix mtPattern2Bitmap;
+ mtPattern2Bitmap.MatchRect(bitmap_rect, cell_bbox);
+
+ auto bitmap_device =
+ CFX_RenderDevice::CreateForBitmapWithBackdropAndGroupKnockout(
+ result_bitmap, /*backdrop_bitmap=*/nullptr, /*group_knockout=*/true);
+ if (!bitmap_device)
+ return nullptr;
+
+ CPDF_RenderOptions options;
+ if (!pTilingPattern->colored())
+ options.SetColorMode(CPDF_RenderOptions::kAlpha);
+ options.GetOptions().bForceHalftone = true;
+
+ CPDF_RenderContext context(&doc, nullptr, nullptr);
+ context.AppendLayer(pPatternForm.get(), mtPattern2Bitmap);
+ context.Render(bitmap_device.get(), nullptr, &options, nullptr);
+
+ CHECK(!result_bitmap->IsPremultiplied());
+
+ // Caller takes ownership.
+ return FPDFBitmapFromCFXDIBitmap(result_bitmap.Leak());
+}
+
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
+FPDFPageObj_GetRenderedStrokePattern(FPDF_DOCUMENT document,
+ FPDF_PAGE page,
+ FPDF_PAGEOBJECT page_object) {
+ CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
+ if (!doc)
+ return nullptr;
+
+ CPDF_Page* optional_page = CPDFPageFromFPDFPage(page);
+ if (optional_page && optional_page->GetDocument() != doc)
+ return nullptr;
+
+ CPDF_PageObject* object = CPDFPageObjectFromFPDFPageObject(page_object);
+ if (!object)
+ return nullptr;
+
+ const CPDF_Color* stroke = object->color_state().GetStrokeColor();
+ if (!stroke || !stroke->IsPattern())
+ return nullptr;
+
+ RetainPtr<CPDF_Pattern> pattern = stroke->GetPattern();
+ if (!pattern)
+ return nullptr;
+
+ return FPDFPageObj_GetRenderedPattern(*pattern, *doc, *object, optional_page);
+}
+
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
+FPDFPageObj_GetRenderedFillPattern(FPDF_DOCUMENT document,
+ FPDF_PAGE page,
+ FPDF_PAGEOBJECT page_object) {
+ CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
+ if (!doc)
+ return nullptr;
+
+ CPDF_Page* optional_page = CPDFPageFromFPDFPage(page);
+ if (optional_page && optional_page->GetDocument() != doc)
+ return nullptr;
+
+ CPDF_PageObject* object = CPDFPageObjectFromFPDFPageObject(page_object);
+ if (!object)
+ return nullptr;
+
+ const CPDF_Color* fill = object->color_state().GetFillColor();
+ if (!fill || !fill->IsPattern())
+ return nullptr;
+
+ RetainPtr<CPDF_Pattern> pattern = fill->GetPattern();
+ if (!pattern)
+ return nullptr;
+
+ return FPDFPageObj_GetRenderedPattern(*pattern, *doc, *object, optional_page);
+}
+
FPDF_EXPORT void FPDF_CALLCONV FPDFFont_Close(FPDF_FONT font) {
// Take back ownership from caller and release.
RetainPtr<CPDF_Font>().Unleak(CPDFFontFromFPDFFont(font));
--- public/fpdf_edit.h 2025-10-17 15:44:08.415888612 +0100
+++ public/fpdf_edit.h 2025-10-17 15:44:12.022555158 +0100
@@ -1417,6 +1417,41 @@
float scale);
// Experimental API.
+// Get a bitmap rasterization of the stroke pattern of |page object|.
+// To render correctly, the caller must provide the |document| associated with
+// |page_object|. If there is a |page| associated with |page_object|, the
+// caller should provide that as well. The returned bitmap will be owned by
+// the caller, and FPDFBitmap_Destroy() must be called on the returned bitmap
+// when it is no longer needed.
+//
+// document - handle to a document associated with |page_object|.
+// page - handle to an optional page associated with |page_object|.
+// page_object - handle to a page object.
+//
+// Returns the bitmap or NULL if the stroke is not a pattern or on failure.
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
+FPDFPageObj_GetRenderedStrokePattern(FPDF_DOCUMENT document,
+ FPDF_PAGE page,
+ FPDF_PAGEOBJECT page_object);
+
+// Get a bitmap rasterization of the fill pattern of |page object|.
+// To render correctly, the caller must provide the |document| associated with
+// |page_object|. If there is a |page| associated with |page_object|, the
+// caller should provide that as well. The returned bitmap will be owned by
+// the caller, and FPDFBitmap_Destroy() must be called on the returned bitmap
+// when it is no longer needed.
+//
+// document - handle to a document associated with |page_object|.
+// page - handle to an optional page associated with |page_object|.
+// page_object - handle to a page object.
+//
+// Returns the bitmap or NULL if the fill is not a pattern or on failure.
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
+FPDFPageObj_GetRenderedFillPattern(FPDF_DOCUMENT document,
+ FPDF_PAGE page,
+ FPDF_PAGEOBJECT page_object);
+
+// Experimental API.
// Get the font of a text object.
//
// text - the handle to the text object.
+1 -1
View File
@@ -33,7 +33,7 @@ $(call gb_ExternalProject_get_state_target,xmlsec,build) :
$(call gb_Trace_StartRange,xmlsec,EXTERNAL)
$(call gb_ExternalProject_run,build,\
cscript /e:javascript configure.js crypto=mscng xslt=no iconv=no static=no \
lib=$(gb_UnpackedTarball_workdir)/libxml2/$(if $(MSVC_USE_DEBUG_RUNTIME),Debug,Release) \
lib=$(gb_UnpackedTarball_workdir)/libxml2 \
$(if $(filter TRUE,$(ENABLE_DBGUTIL)),debug=yes cruntime=/MDd) \
cflags="$(SOLARINC) $(LIBXML_CFLAGS)" \
&& nmake \

Some files were not shown because too many files have changed in this diff Show More