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 )
{
m_xFT_RANGE->set_label(
m_aFixedTextRange.replaceAt(
nIndex, aReplacementStr.getLength(), aSelectedRoleUI ));
}
// add the role in fixed text label
m_xFT_RANGE->set_label(
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);
+186 -178
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_xLevelLB->unselect(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,55 +2167,59 @@ 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 )),
FieldUnit::MM_100TH);
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 )),
FieldUnit::MM_100TH);
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);
}
}
const SvxBrushItem* pBrushItem = aNumFmt.GetBrush();
@@ -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>
+1 -1
View File
@@ -403,7 +403,7 @@
<property name="digits">2</property>
<child internal-child="accessible">
<object class="AtkObject" id="spinMargLeft-atkobject">
<property name="AtkObject::accessible-description" translatable="yes" context="pageformatpage|extended-tip|spinMarginLeft">Enter the amount of space to leave between the left edge of the page and the document text. If you are using the Mirrored page layout, enter the amount of space to leave between the inner text margin and the inner edge of the page.</property>
<property name="AtkObject::accessible-description" translatable="yes" context="pageformatpage|extended-tip|spinMarginLeft">Enter the amount of space to leave between the left edge of the page and the document text. If you are using the Mirrored page layout, enter the amount of space to leave between the inner text margin and the inner edge of the page.</property>
</object>
</child>
</object>
+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;
}
}
+18 -4
View File
@@ -1361,8 +1361,14 @@ FeatureState SbaXDataBrowserController::GetState(sal_uInt16 nId) const
aReturn.bEnabled = false;
return aReturn;
}
// any filter or sort order set ?
aReturn.bEnabled = m_xParser->getFilter().getLength() || m_xParser->getHavingClause().getLength() || m_xParser->getOrder().getLength();
{
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 = !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);
mpPDFExtOutDevData->WrapBeginStructureElement(
vcl::pdf::StructElement::NonStructElement);
}
}
@@ -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.

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