summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]l10ntools/scripts/localize.pl0
-rwxr-xr-x[-rw-r--r--]l10ntools/scripts/localize_old.pl0
-rw-r--r--sax/inc/sax/tools/converter.hxx1
-rw-r--r--sax/prj/build.lst1
-rw-r--r--sax/qa/cppunit/makefile.mk71
-rw-r--r--sax/qa/cppunit/test_converter.cxx244
-rw-r--r--sax/qa/cppunit/version.map34
-rw-r--r--sax/source/tools/converter.cxx165
-rw-r--r--svl/source/items/nranges.cxx2
-rw-r--r--svl/source/items/srchitem.cxx72
-rw-r--r--tools/source/stream/strmunx.cxx4
-rw-r--r--vcl/inc/vcl/graphite_cache.hxx19
-rw-r--r--vcl/inc/vcl/graphite_layout.hxx9
-rw-r--r--vcl/source/glyphs/graphite_layout.cxx227
14 files changed, 585 insertions, 264 deletions
diff --git a/l10ntools/scripts/localize.pl b/l10ntools/scripts/localize.pl
index 82ef331a63d5..82ef331a63d5 100644..100755
--- a/l10ntools/scripts/localize.pl
+++ b/l10ntools/scripts/localize.pl
diff --git a/l10ntools/scripts/localize_old.pl b/l10ntools/scripts/localize_old.pl
index d6b66d6bb535..d6b66d6bb535 100644..100755
--- a/l10ntools/scripts/localize_old.pl
+++ b/l10ntools/scripts/localize_old.pl
diff --git a/sax/inc/sax/tools/converter.hxx b/sax/inc/sax/tools/converter.hxx
index 1e783b4a4ec9..4b65c1dc83b2 100644
--- a/sax/inc/sax/tools/converter.hxx
+++ b/sax/inc/sax/tools/converter.hxx
@@ -32,6 +32,7 @@
#include <sal/types.h>
+#include <com/sun/star/uno/Sequence.h>
#include <com/sun/star/util/MeasureUnit.hpp>
diff --git a/sax/prj/build.lst b/sax/prj/build.lst
index e3f70c484610..653d77ce9e25 100644
--- a/sax/prj/build.lst
+++ b/sax/prj/build.lst
@@ -3,3 +3,4 @@ ax sax usr1 - all ax_mkout NULL
ax sax\source\expatwrap nmake - all ax_expatwrap NULL
ax sax\source\tools nmake - all ax_tools NULL
ax sax\source\fastparser nmake - all ax_fastparser ax_expatwrap ax_tools NULL
+ax sax\qa\cppunit nmake - all ax_qa_cppunit ax_tools NULL
diff --git a/sax/qa/cppunit/makefile.mk b/sax/qa/cppunit/makefile.mk
new file mode 100644
index 000000000000..e06eca25a737
--- /dev/null
+++ b/sax/qa/cppunit/makefile.mk
@@ -0,0 +1,71 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=../..
+PRJNAME=sax
+TARGET=qa_cppunit
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+CFLAGSCXX += $(CPPUNIT_CFLAGS)
+DLLPRE = # no leading "lib" on .so files
+
+# --- Libs ---------------------------------------------------------
+
+SHL1OBJS= \
+ $(SLO)/test_converter.obj \
+
+
+SHL1STDLIBS= \
+ $(SAXLIB) \
+ $(SALLIB) \
+ $(CPPUNITLIB) \
+
+
+SHL1TARGET= test_converter
+SHL1RPATH = NONE
+SHL1IMPLIB= i$(SHL1TARGET)
+# SHL1DEF= $(MISC)/$(SHL1TARGET).def
+DEF1NAME=$(SHL1TARGET)
+# DEF1EXPORTFILE= export.exp
+SHL1VERSIONMAP= version.map
+
+# --- All object files ---------------------------------------------
+
+SLOFILES= \
+ $(SHL1OBJS) \
+
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+.INCLUDE : _cppunit.mk
+
diff --git a/sax/qa/cppunit/test_converter.cxx b/sax/qa/cppunit/test_converter.cxx
new file mode 100644
index 000000000000..1ea781afff95
--- /dev/null
+++ b/sax/qa/cppunit/test_converter.cxx
@@ -0,0 +1,244 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <rtl/ustrbuf.hxx>
+
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Duration.hpp>
+
+#include "sax/tools/converter.hxx"
+
+
+using namespace ::com::sun::star;
+using sax::Converter;
+
+
+namespace {
+
+class ConverterTest
+ : public ::CppUnit::TestFixture
+{
+public:
+ virtual void setUp();
+ virtual void tearDown();
+
+ void testDuration();
+ void testDateTime();
+
+ CPPUNIT_TEST_SUITE(ConverterTest);
+ CPPUNIT_TEST(testDuration);
+ CPPUNIT_TEST(testDateTime);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+};
+
+void ConverterTest::setUp()
+{
+}
+
+void ConverterTest::tearDown()
+{
+}
+
+static bool eqDuration(util::Duration a, util::Duration b) {
+ return a.Years == b.Years && a.Months == b.Months && a.Days == b.Days
+ && a.Hours == b.Hours && a.Minutes == b.Minutes
+ && a.Seconds == b.Seconds
+ && a.MilliSeconds == b.MilliSeconds
+ && a.Negative == b.Negative;
+}
+
+static void doTest(util::Duration const & rid, char const*const pis,
+ char const*const i_pos = 0)
+{
+ char const*const pos((i_pos) ? i_pos : pis);
+ util::Duration od;
+ ::rtl::OUString is(::rtl::OUString::createFromAscii(pis));
+ bool bSuccess = Converter::convertDuration(od, is);
+ OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dm",
+ od.Negative, od.Years, od.Months, od.Days,
+ od.Hours, od.Minutes, od.Seconds, od.MilliSeconds);
+ CPPUNIT_ASSERT(bSuccess);
+ CPPUNIT_ASSERT(eqDuration(rid, od));
+ ::rtl::OUStringBuffer buf;
+ Converter::convertDuration(buf, od);
+ OSL_TRACE(
+ ::rtl::OUStringToOString(buf.getStr(), RTL_TEXTENCODING_UTF8));
+ CPPUNIT_ASSERT(buf.makeStringAndClear().equalsAscii(pos));
+}
+
+static void doTestDurationF(char const*const pis)
+{
+ util::Duration od;
+ bool bSuccess = Converter::convertDuration(od,
+ ::rtl::OUString::createFromAscii(pis));
+ OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dH",
+ od.Negative, od.Years, od.Months, od.Days,
+ od.Hours, od.Minutes, od.Seconds, od.MilliSeconds);
+ CPPUNIT_ASSERT(!bSuccess);
+}
+
+void ConverterTest::testDuration()
+{
+ OSL_TRACE("\nSAX CONVERTER TEST BEGIN\n");
+ doTest( util::Duration(false, 1, 0, 0, 0, 0, 0, 0), "P1Y" );
+ doTest( util::Duration(false, 0, 42, 0, 0, 0, 0, 0), "P42M" );
+ doTest( util::Duration(false, 0, 0, 111, 0, 0, 0, 0), "P111D" );
+ doTest( util::Duration(false, 0, 0, 0, 52, 0, 0, 0), "PT52H" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 717, 0, 0), "PT717M" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 121, 0), "PT121S" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 190), "PT0.19S" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 90), "PT0.09S" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 9), "PT0.009S" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 9, 999),
+ "PT9.999999999999999999999999999999S", "PT9.999S" );
+ doTest( util::Duration(true , 0, 0, 9999, 0, 0, 0, 0), "-P9999D" );
+ doTest( util::Duration(true , 7, 6, 5, 4, 3, 2, 10),
+ "-P7Y6M5DT4H3M2.01S" );
+ doTest( util::Duration(false, 0, 6, 0, 0, 3, 0, 0), "P6MT3M" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 0), "P0D" );
+ doTestDurationF("1Y1M"); // invalid: no ^P
+ doTestDurationF("P-1Y1M"); // invalid: - after P
+ doTestDurationF("P1M1Y"); // invalid: Y after M
+ doTestDurationF("PT1Y"); // invalid: Y after T
+ doTestDurationF("P1Y1M1M"); // invalid: M twice, no T
+ doTestDurationF("P1YT1MT1M"); // invalid: T twice
+ doTestDurationF("P1YT"); // invalid: T but no H,M,S
+ doTestDurationF("P99999999999Y"); // cannot parse so many Ys
+ doTestDurationF("PT.1S"); // invalid: no 0 preceding .
+ doTestDurationF("PT5M.134S"); // invalid: no 0 preceding .
+ doTestDurationF("PT1.S"); // invalid: no digit following .
+ OSL_TRACE("\nSAX CONVERTER TEST END\n");
+}
+
+
+static bool eqDateTime(util::DateTime a, util::DateTime b) {
+ return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day
+ && a.Hours == b.Hours && a.Minutes == b.Minutes
+ && a.Seconds == b.Seconds
+ && a.HundredthSeconds == b.HundredthSeconds;
+}
+
+static void doTest(util::DateTime const & rdt, char const*const pis,
+ char const*const i_pos = 0)
+{
+ char const*const pos((i_pos) ? i_pos : pis);
+ ::rtl::OUString is(::rtl::OUString::createFromAscii(pis));
+ util::DateTime odt;
+ bool bSuccess( Converter::convertDateTime(odt, is) );
+ OSL_TRACE("Y:%d M:%d D:%d H:%d M:%d S:%d H:%d",
+ odt.Year, odt.Month, odt.Day,
+ odt.Hours, odt.Minutes, odt.Seconds, odt.HundredthSeconds);
+ CPPUNIT_ASSERT(bSuccess);
+ CPPUNIT_ASSERT(eqDateTime(rdt, odt));
+ ::rtl::OUStringBuffer buf;
+ Converter::convertDateTime(buf, odt, true);
+ OSL_TRACE(
+ ::rtl::OUStringToOString(buf.getStr(), RTL_TEXTENCODING_UTF8));
+ CPPUNIT_ASSERT(buf.makeStringAndClear().equalsAscii(pos));
+}
+
+static void doTestDateTimeF(char const*const pis)
+{
+ util::DateTime odt;
+ bool bSuccess = Converter::convertDateTime(odt,
+ ::rtl::OUString::createFromAscii(pis));
+ OSL_TRACE("Y:%d M:%d D:%d H:%dH M:%d S:%d H:%d",
+ odt.Year, odt.Month, odt.Day,
+ odt.Hours, odt.Minutes, odt.Seconds, odt.HundredthSeconds);
+ CPPUNIT_ASSERT(!bSuccess);
+}
+
+void ConverterTest::testDateTime()
+{
+ OSL_TRACE("\nSAX CONVERTER TEST BEGIN\n");
+ doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1), "0001-01-01T00:00:00" );
+ doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1),
+ "0001-01-01T00:00:00Z", "0001-01-01T00:00:00" );
+// doTest( util::DateTime(0, 0, 0, 0, 1, 1, -1), "-0001-01-01T00:00:00" );
+// doTest( util::DateTime(0, 0, 0, 0, 1, 1, -1), "-0001-01-01T00:00:00Z" );
+ doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1),
+ "0001-01-01T00:00:00-00:00", "0001-01-01T00:00:00" );
+ doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1),
+ "0001-01-01T00:00:00+00:00", "0001-01-01T00:00:00" );
+ doTest( util::DateTime(0, 0, 0, 0, 2, 1, 1)/*(0, 0, 12, 0, 2, 1, 1)*/,
+ "0001-01-02T00:00:00-12:00", "0001-01-02T00:00:00" );
+// "0001-02-01T12:00:00" );
+ doTest( util::DateTime(0, 0, 0, 0, 2, 1, 1)/*(0, 0, 12, 0, 1, 1, 1)*/,
+ "0001-01-02T00:00:00+12:00", "0001-01-02T00:00:00" );
+// "0001-01-01T12:00:00" );
+ doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
+ "9999-12-31T23:59:59.99" );
+ doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
+ "9999-12-31T23:59:59.99Z", "9999-12-31T23:59:59.99" );
+ doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
+ "9999-12-31T23:59:59.9999999999999999999999999999999999999",
+ "9999-12-31T23:59:59.99" );
+ doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
+ "9999-12-31T23:59:59.9999999999999999999999999999999999999Z",
+ "9999-12-31T23:59:59.99" );
+ doTest( util::DateTime(0, 0, 0, 24, 1, 1, 333)
+ /*(0, 0, 0, 0, 2, 1, 333)*/,
+ "0333-01-01T24:00:00"/*, "0333-01-02T00:00:00"*/ );
+ doTestDateTimeF( "+0001-01-01T00:00:00" ); // invalid: ^+
+ doTestDateTimeF( "1-01-01T00:00:00" ); // invalid: < 4 Y
+ doTestDateTimeF( "0001-1-01T00:00:00" ); // invalid: < 2 M
+ doTestDateTimeF( "0001-01-1T00:00:00" ); // invalid: < 2 D
+ doTestDateTimeF( "0001-01-01T0:00:00" ); // invalid: < 2 H
+ doTestDateTimeF( "0001-01-01T00:0:00" ); // invalid: < 2 M
+ doTestDateTimeF( "0001-01-01T00:00:0" ); // invalid: < 2 S
+ doTestDateTimeF( "0001-01-01T00:00:00." ); // invalid: .$
+ doTestDateTimeF( "0001-01-01T00:00:00+1:00" ); // invalid: < 2 TZ H
+ doTestDateTimeF( "0001-01-01T00:00:00+00:1" ); // invalid: < 2 TZ M
+ doTestDateTimeF( "0001-13-01T00:00:00" ); // invalid: M > 12
+ doTestDateTimeF( "0001-01-32T00:00:00" ); // invalid: D > 31
+ doTestDateTimeF( "0001-01-01T25:00:00" ); // invalid: H > 24
+ doTestDateTimeF( "0001-01-01T00:60:00" ); // invalid: H > 59
+ doTestDateTimeF( "0001-01-01T00:00:60" ); // invalid: S > 59
+ doTestDateTimeF( "0001-01-01T24:01:00" ); // invalid: H=24, but M != 0
+ doTestDateTimeF( "0001-01-01T24:00:01" ); // invalid: H=24, but S != 0
+ doTestDateTimeF( "0001-01-01T24:00:00.1" ); // invalid: H=24, but H != 0
+ doTestDateTimeF( "0001-01-02T00:00:00+15:00" ); // invalid: TZ > +14:00
+ doTestDateTimeF( "0001-01-02T00:00:00+14:01" ); // invalid: TZ > +14:00
+ doTestDateTimeF( "0001-01-02T00:00:00-15:00" ); // invalid: TZ < -14:00
+ doTestDateTimeF( "0001-01-02T00:00:00-14:01" ); // invalid: TZ < -14:00
+ OSL_TRACE("\nSAX CONVERTER TEST END\n");
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ConverterTest);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
diff --git a/sax/qa/cppunit/version.map b/sax/qa/cppunit/version.map
new file mode 100644
index 000000000000..3308588ef6f8
--- /dev/null
+++ b/sax/qa/cppunit/version.map
@@ -0,0 +1,34 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+UDK_3_0_0 {
+ global:
+ cppunitTestPlugIn;
+
+ local:
+ *;
+};
diff --git a/sax/source/tools/converter.cxx b/sax/source/tools/converter.cxx
index 35bfba29c904..5df3044bd6d3 100644
--- a/sax/source/tools/converter.cxx
+++ b/sax/source/tools/converter.cxx
@@ -1217,78 +1217,6 @@ bool Converter::convertDuration(util::Duration& rDuration,
return bSuccess;
}
-#if 0
-//FIXME
-struct Test {
- static bool eqDuration(util::Duration a, util::Duration b) {
- return a.Years == b.Years && a.Months == b.Months && a.Days == b.Days
- && a.Hours == b.Hours && a.Minutes == b.Minutes
- && a.Seconds == b.Seconds
- && a.MilliSeconds == b.MilliSeconds
- && a.Negative == b.Negative;
- }
- static void doTest(util::Duration const & rid, char const*const pis,
- char const*const i_pos = 0)
- {
- char const*const pos((i_pos) ? i_pos : pis);
- util::Duration od;
- ::rtl::OUString is(::rtl::OUString::createFromAscii(pis));
- bool bSuccess = Converter::convertDuration(od, is);
- OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dm",
- od.Negative, od.Years, od.Months, od.Days,
- od.Hours, od.Minutes, od.Seconds, od.MilliSeconds);
- OSL_ASSERT(bSuccess);
- OSL_ASSERT(eqDuration(rid, od));
- ::rtl::OUStringBuffer buf;
- Converter::convertDuration(buf, od);
- OSL_TRACE(
- ::rtl::OUStringToOString(buf.getStr(), RTL_TEXTENCODING_UTF8));
- OSL_ASSERT(buf.makeStringAndClear().equalsAscii(pos));
- }
- static void doTestF(const char * pis)
- {
- util::Duration od;
- bool bSuccess = Converter::convertDuration(od,
- ::rtl::OUString::createFromAscii(pis));
- OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dH",
- od.Negative, od.Years, od.Months, od.Days,
- od.Hours, od.Minutes, od.Seconds, od.MilliSeconds);
- OSL_ASSERT(!bSuccess);
- }
- Test() {
- OSL_TRACE("\nSAX CONVERTER TEST BEGIN\n");
- doTest( util::Duration(false, 1, 0, 0, 0, 0, 0, 0), "P1Y" );
- doTest( util::Duration(false, 0, 42, 0, 0, 0, 0, 0), "P42M" );
- doTest( util::Duration(false, 0, 0, 111, 0, 0, 0, 0), "P111D" );
- doTest( util::Duration(false, 0, 0, 0, 52, 0, 0, 0), "PT52H" );
- doTest( util::Duration(false, 0, 0, 0, 0, 717, 0, 0), "PT717M" );
- doTest( util::Duration(false, 0, 0, 0, 0, 0, 121, 0), "PT121S" );
- doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 190), "PT0.19S" );
- doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 90), "PT0.09S" );
- doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 9), "PT0.009S" );
- doTest( util::Duration(false, 0, 0, 0, 0, 0, 9, 999),
- "PT9.999999999999999999999999999999S", "PT9.999S" );
- doTest( util::Duration(true , 0, 0, 9999, 0, 0, 0, 0), "-P9999D" );
- doTest( util::Duration(true , 7, 6, 5, 4, 3, 2, 10),
- "-P7Y6M5DT4H3M2.01S" );
- doTest( util::Duration(false, 0, 6, 0, 0, 3, 0, 0), "P6MT3M" );
- doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 0), "P0D" );
- doTestF("1Y1M"); // invalid: no ^P
- doTestF("P-1Y1M"); // invalid: - after P
- doTestF("P1M1Y"); // invalid: Y after M
- doTestF("PT1Y"); // invalid: Y after T
- doTestF("P1Y1M1M"); // invalid: M twice, no T
- doTestF("P1YT1MT1M"); // invalid: T twice
- doTestF("P1YT"); // invalid: T but no H,M,S
- doTestF("P99999999999Y"); // cannot parse so many Ys
- doTestF("PT.1S"); // invalid: no 0 preceding .
- doTestF("PT5M.134S"); // invalid: no 0 preceding .
- doTestF("PT1.S"); // invalid: no digit following .
- OSL_TRACE("\nSAX CONVERTER TEST END\n");
- }
-};
-static Test test;
-#endif
/** convert util::Date to ISO "date" string */
void Converter::convertDate(
@@ -1675,99 +1603,6 @@ bool Converter::convertDateOrDateTime(
return bSuccess;
}
-#if 0
-struct Test {
- static bool eqDateTime(util::DateTime a, util::DateTime b) {
- return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day
- && a.Hours == b.Hours && a.Minutes == b.Minutes
- && a.Seconds == b.Seconds
- && a.HundredthSeconds == b.HundredthSeconds;
- }
- static void doTest(util::DateTime const & rdt, char const*const pis,
- char const*const i_pos = 0)
- {
- char const*const pos((i_pos) ? i_pos : pis);
- ::rtl::OUString is(::rtl::OUString::createFromAscii(pis));
- util::DateTime odt;
- bool bSuccess( Converter::convertDateTime(odt, is) );
- OSL_TRACE("Y:%d M:%d D:%d H:%d M:%d S:%d H:%d",
- odt.Year, odt.Month, odt.Day,
- odt.Hours, odt.Minutes, odt.Seconds, odt.HundredthSeconds);
- OSL_ASSERT(bSuccess);
- OSL_ASSERT(eqDateTime(rdt, odt));
- ::rtl::OUStringBuffer buf;
- Converter::convertDateTime(buf, odt, true);
- OSL_TRACE(
- ::rtl::OUStringToOString(buf.getStr(), RTL_TEXTENCODING_UTF8));
- OSL_ASSERT(buf.makeStringAndClear().equalsAscii(pos));
- }
- static void doTestF(const char * pis)
- {
- util::DateTime odt;
- bool bSuccess = Converter::convertDateTime(odt,
- ::rtl::OUString::createFromAscii(pis));
- OSL_TRACE("Y:%d M:%d D:%d H:%dH M:%d S:%d H:%d",
- odt.Year, odt.Month, odt.Day,
- odt.Hours, odt.Minutes, odt.Seconds, odt.HundredthSeconds);
- OSL_ASSERT(!bSuccess);
- }
- Test() {
- OSL_TRACE("\nSAX CONVERTER TEST BEGIN\n");
- doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1), "0001-01-01T00:00:00" );
- doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1),
- "0001-01-01T00:00:00Z", "0001-01-01T00:00:00" );
-// doTest( util::DateTime(0, 0, 0, 0, 1, 1, -1), "-0001-01-01T00:00:00" );
-// doTest( util::DateTime(0, 0, 0, 0, 1, 1, -1), "-0001-01-01T00:00:00Z" );
- doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1),
- "0001-01-01T00:00:00-00:00", "0001-01-01T00:00:00" );
- doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1),
- "0001-01-01T00:00:00+00:00", "0001-01-01T00:00:00" );
- doTest( util::DateTime(0, 0, 0, 0, 2, 1, 1)/*(0, 0, 12, 0, 2, 1, 1)*/,
- "0001-01-02T00:00:00-12:00", "0001-01-02T00:00:00" );
-// "0001-02-01T12:00:00" );
- doTest( util::DateTime(0, 0, 0, 0, 2, 1, 1)/*(0, 0, 12, 0, 1, 1, 1)*/,
- "0001-01-02T00:00:00+12:00", "0001-01-02T00:00:00" );
-// "0001-01-01T12:00:00" );
- doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
- "9999-12-31T23:59:59.99" );
- doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
- "9999-12-31T23:59:59.99Z", "9999-12-31T23:59:59.99" );
- doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
- "9999-12-31T23:59:59.9999999999999999999999999999999999999",
- "9999-12-31T23:59:59.99" );
- doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
- "9999-12-31T23:59:59.9999999999999999999999999999999999999Z",
- "9999-12-31T23:59:59.99" );
- doTest( util::DateTime(0, 0, 0, 24, 1, 1, 333)
- /*(0, 0, 0, 0, 2, 1, 333)*/,
- "0333-01-01T24:00:00"/*, "0333-01-02T00:00:00"*/ );
- doTestF( "+0001-01-01T00:00:00" ); // invalid: ^+
- doTestF( "1-01-01T00:00:00" ); // invalid: < 4 Y
- doTestF( "0001-1-01T00:00:00" ); // invalid: < 2 M
- doTestF( "0001-01-1T00:00:00" ); // invalid: < 2 D
- doTestF( "0001-01-01T0:00:00" ); // invalid: < 2 H
- doTestF( "0001-01-01T00:0:00" ); // invalid: < 2 M
- doTestF( "0001-01-01T00:00:0" ); // invalid: < 2 S
- doTestF( "0001-01-01T00:00:00." ); // invalid: .$
- doTestF( "0001-01-01T00:00:00+1:00" ); // invalid: < 2 TZ H
- doTestF( "0001-01-01T00:00:00+00:1" ); // invalid: < 2 TZ M
- doTestF( "0001-13-01T00:00:00" ); // invalid: M > 12
- doTestF( "0001-01-32T00:00:00" ); // invalid: D > 31
- doTestF( "0001-01-01T25:00:00" ); // invalid: H > 24
- doTestF( "0001-01-01T00:60:00" ); // invalid: H > 59
- doTestF( "0001-01-01T00:00:60" ); // invalid: S > 59
- doTestF( "0001-01-01T24:01:00" ); // invalid: H=24, but M != 0
- doTestF( "0001-01-01T24:00:01" ); // invalid: H=24, but S != 0
- doTestF( "0001-01-01T24:00:00.1" ); // invalid: H=24, but H != 0
- doTestF( "0001-01-02T00:00:00+15:00" ); // invalid: TZ > +14:00
- doTestF( "0001-01-02T00:00:00+14:01" ); // invalid: TZ > +14:00
- doTestF( "0001-01-02T00:00:00-15:00" ); // invalid: TZ < -14:00
- doTestF( "0001-01-02T00:00:00-14:01" ); // invalid: TZ < -14:00
- OSL_TRACE("\nSAX CONVERTER TEST END\n");
- }
-};
-static Test test;
-#endif
/** gets the position of the first comma after npos in the string
rStr. Commas inside '"' pairs are not matched */
diff --git a/svl/source/items/nranges.cxx b/svl/source/items/nranges.cxx
index 284bc251a3a4..ae633276300f 100644
--- a/svl/source/items/nranges.cxx
+++ b/svl/source/items/nranges.cxx
@@ -480,7 +480,6 @@ SfxNumRanges& SfxNumRanges::operator -=
NUMTYPE nThisSize = Count_Impl(_pRanges);
NUMTYPE nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) );
NUMTYPE *pTarget = new NUMTYPE[ nTargetSize ];
- memset( pTarget, sizeof(NUMTYPE)*nTargetSize, 0 );
memcpy( pTarget, _pRanges, sizeof(NUMTYPE)*nThisSize );
NUMTYPE nPos1 = 0, nPos2 = 0, nTargetPos = 0;
@@ -690,7 +689,6 @@ SfxNumRanges& SfxNumRanges::operator /=
NUMTYPE nThisSize = Count_Impl(_pRanges);
NUMTYPE nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) );
NUMTYPE *pTarget = new NUMTYPE[ nTargetSize ];
- memset( pTarget, sizeof(NUMTYPE)*nTargetSize, 0 );
memcpy( pTarget, _pRanges, sizeof(NUMTYPE)*nThisSize );
NUMTYPE nPos1 = 0, nPos2 = 0, nTargetPos = 0;
diff --git a/svl/source/items/srchitem.cxx b/svl/source/items/srchitem.cxx
index b7422c56224b..cc033bc6905e 100644
--- a/svl/source/items/srchitem.cxx
+++ b/svl/source/items/srchitem.cxx
@@ -151,40 +151,44 @@ SvxSearchItem::SvxSearchItem( const sal_uInt16 nId ) :
rFlags |= TransliterationModules_IGNORE_CASE;
if ( aOpt.IsMatchFullHalfWidthForms())
rFlags |= TransliterationModules_IGNORE_WIDTH;
- if ( aOpt.IsMatchHiraganaKatakana())
- rFlags |= TransliterationModules_IGNORE_KANA;
- if ( aOpt.IsMatchContractions())
- rFlags |= TransliterationModules_ignoreSize_ja_JP;
- if ( aOpt.IsMatchMinusDashChoon())
- rFlags |= TransliterationModules_ignoreMinusSign_ja_JP;
- if ( aOpt.IsMatchRepeatCharMarks())
- rFlags |= TransliterationModules_ignoreIterationMark_ja_JP;
- if ( aOpt.IsMatchVariantFormKanji())
- rFlags |= TransliterationModules_ignoreTraditionalKanji_ja_JP;
- if ( aOpt.IsMatchOldKanaForms())
- rFlags |= TransliterationModules_ignoreTraditionalKana_ja_JP;
- if ( aOpt.IsMatchDiziDuzu())
- rFlags |= TransliterationModules_ignoreZiZu_ja_JP;
- if ( aOpt.IsMatchBavaHafa())
- rFlags |= TransliterationModules_ignoreBaFa_ja_JP;
- if ( aOpt.IsMatchTsithichiDhizi())
- rFlags |= TransliterationModules_ignoreTiJi_ja_JP;
- if ( aOpt.IsMatchHyuiyuByuvyu())
- rFlags |= TransliterationModules_ignoreHyuByu_ja_JP;
- if ( aOpt.IsMatchSesheZeje())
- rFlags |= TransliterationModules_ignoreSeZe_ja_JP;
- if ( aOpt.IsMatchIaiya())
- rFlags |= TransliterationModules_ignoreIandEfollowedByYa_ja_JP;
- if ( aOpt.IsMatchKiku())
- rFlags |= TransliterationModules_ignoreKiKuFollowedBySa_ja_JP;
- if ( aOpt.IsIgnorePunctuation())
- rFlags |= TransliterationModules_ignoreSeparator_ja_JP;
- if ( aOpt.IsIgnoreWhitespace())
- rFlags |= TransliterationModules_ignoreSpace_ja_JP;
- if ( aOpt.IsIgnoreProlongedSoundMark())
- rFlags |= TransliterationModules_ignoreProlongedSoundMark_ja_JP;
- if ( aOpt.IsIgnoreMiddleDot())
- rFlags |= TransliterationModules_ignoreMiddleDot_ja_JP;
+ if ( bAsianOptions )
+ {
+ if ( aOpt.IsMatchHiraganaKatakana())
+ rFlags |= TransliterationModules_IGNORE_KANA;
+ if ( aOpt.IsMatchContractions())
+ rFlags |= TransliterationModules_ignoreSize_ja_JP;
+ if ( aOpt.IsMatchMinusDashChoon())
+ rFlags |= TransliterationModules_ignoreMinusSign_ja_JP;
+ if ( aOpt.IsMatchRepeatCharMarks())
+ rFlags |= TransliterationModules_ignoreIterationMark_ja_JP;
+ if ( aOpt.IsMatchVariantFormKanji())
+ rFlags |= TransliterationModules_ignoreTraditionalKanji_ja_JP;
+ if ( aOpt.IsMatchOldKanaForms())
+ rFlags |= TransliterationModules_ignoreTraditionalKana_ja_JP;
+ if ( aOpt.IsMatchDiziDuzu())
+ rFlags |= TransliterationModules_ignoreZiZu_ja_JP;
+ if ( aOpt.IsMatchBavaHafa())
+ rFlags |= TransliterationModules_ignoreBaFa_ja_JP;
+ if ( aOpt.IsMatchTsithichiDhizi())
+ rFlags |= TransliterationModules_ignoreTiJi_ja_JP;
+ if ( aOpt.IsMatchHyuiyuByuvyu())
+ rFlags |= TransliterationModules_ignoreHyuByu_ja_JP;
+ if ( aOpt.IsMatchSesheZeje())
+ rFlags |= TransliterationModules_ignoreSeZe_ja_JP;
+ if ( aOpt.IsMatchIaiya())
+ rFlags |= TransliterationModules_ignoreIandEfollowedByYa_ja_JP;
+ if ( aOpt.IsMatchKiku())
+ rFlags |= TransliterationModules_ignoreKiKuFollowedBySa_ja_JP;
+ if ( aOpt.IsIgnorePunctuation())
+ rFlags |= TransliterationModules_ignoreSeparator_ja_JP;
+ if ( aOpt.IsIgnoreWhitespace())
+ rFlags |= TransliterationModules_ignoreSpace_ja_JP;
+ if ( aOpt.IsIgnoreProlongedSoundMark())
+ rFlags |= TransliterationModules_ignoreProlongedSoundMark_ja_JP;
+ if ( aOpt.IsIgnoreMiddleDot())
+ rFlags |= TransliterationModules_ignoreMiddleDot_ja_JP;
+ }
+
}
// -----------------------------------------------------------------------
diff --git a/tools/source/stream/strmunx.cxx b/tools/source/stream/strmunx.cxx
index 9e4f501d1823..88ccb2113e0d 100644
--- a/tools/source/stream/strmunx.cxx
+++ b/tools/source/stream/strmunx.cxx
@@ -209,7 +209,7 @@ static sal_uInt32 GetSvError( int nErrno )
{ 0, SVSTREAM_OK },
{ EACCES, SVSTREAM_ACCESS_DENIED },
{ EBADF, SVSTREAM_INVALID_HANDLE },
-#if defined( RS6000 ) || defined( ALPHA ) || defined( HP9000 ) || defined( NETBSD ) || defined(FREEBSD) || defined(MACOSX)
+#if defined( RS6000 ) || defined( ALPHA ) || defined( HP9000 ) || defined( NETBSD ) || defined(FREEBSD) || defined(MACOSX) || defined(__FreeBSD_kernel__)
{ EDEADLK, SVSTREAM_LOCKING_VIOLATION },
#else
{ EDEADLOCK, SVSTREAM_LOCKING_VIOLATION },
@@ -223,7 +223,7 @@ static sal_uInt32 GetSvError( int nErrno )
{ EAGAIN, SVSTREAM_LOCKING_VIOLATION },
{ EISDIR, SVSTREAM_PATH_NOT_FOUND },
{ ELOOP, SVSTREAM_PATH_NOT_FOUND },
-#if ! defined( RS6000 ) && ! defined( ALPHA ) && ! defined( NETBSD ) && ! defined (FREEBSD) && ! defined (MACOSX)
+#if ! defined( RS6000 ) && ! defined( ALPHA ) && ! defined( NETBSD ) && ! defined (FREEBSD) && ! defined (MACOSX) && ! defined(__FreeBSD_kernel__)
{ EMULTIHOP, SVSTREAM_PATH_NOT_FOUND },
{ ENOLINK, SVSTREAM_PATH_NOT_FOUND },
#endif
diff --git a/vcl/inc/vcl/graphite_cache.hxx b/vcl/inc/vcl/graphite_cache.hxx
index eba5109c7446..5472b32dd62f 100644
--- a/vcl/inc/vcl/graphite_cache.hxx
+++ b/vcl/inc/vcl/graphite_cache.hxx
@@ -127,7 +127,7 @@ public:
}
m_segMap.clear();
};
- GrSegRecord * getSegment(ImplLayoutArgs & layoutArgs, bool bIsRtl)
+ GrSegRecord * getSegment(ImplLayoutArgs & layoutArgs, bool bIsRtl, int segCharLimit)
{
GrSegRecord * found = NULL;
// try to find a segment starting at correct place, if not, try to find a
@@ -152,8 +152,6 @@ public:
if (found->m_seg->startCharacter() <= layoutArgs.mnMinCharPos &&
found->m_seg->stopCharacter() >= layoutArgs.mnEndCharPos)
{
- const size_t seg_char_limit = min(layoutArgs.mnLength, layoutArgs.mnEndCharPos
- + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
DBG_ASSERT(found && found->m_seg, "null entry in GraphiteSegmentCache");
// restore original start character, in case it has changed
found->m_seg->setTextSourceOffset(found->m_startChar);
@@ -161,7 +159,7 @@ public:
// interest
// We could use substr and ==, but substr does a copy,
// so its probably faster to do it like this
- for (size_t i = layoutArgs.mnMinCharPos; i < seg_char_limit; i++)
+ for (int i = layoutArgs.mnMinCharPos; i < segCharLimit; i++)
{
//if (!found->m_rope->match(rtl::OUString(layoutArgs.mpStr[i], layoutArgs.mnLength), i - found->m_seg->startCharacter()))
if (found->m_rope->getStr()[i-found->m_seg->startCharacter()] != layoutArgs.mpStr[i])
@@ -171,6 +169,15 @@ public:
{
return NULL;
}
+ if (found->m_seg->stopCharacter() > layoutArgs.mnEndCharPos &&
+ static_cast<int>(found->char2BaseGlyph().size()) > layoutArgs.mnEndCharPos)
+ {
+ // check that the requested end character isn't mid cluster
+ if (found->char2BaseGlyph()[layoutArgs.mnEndCharPos-layoutArgs.mnMinCharPos] == -1)
+ {
+ return NULL;
+ }
+ }
// if (found->m_lockCount != 0)
// OutputDebugString("Multple users of SegRecord!");
found->m_lockCount++;
@@ -183,10 +190,8 @@ public:
// this is expecially needed when editing a large paragraph
// each edit changes the pointers, but if we don't reuse any segments it gets very
// slow.
- const size_t seg_char_limit = min(layoutArgs.mnLength, layoutArgs.mnEndCharPos
- + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
rtl::OUString * rope = new rtl::OUString(layoutArgs.mpStr + layoutArgs.mnMinCharPos,
- seg_char_limit - layoutArgs.mnMinCharPos);
+ segCharLimit - layoutArgs.mnMinCharPos);
if (!rope) return NULL;
size_t nHash = (*(rope)).hashCode();
GrRMEntry range = m_ropeMap.equal_range(nHash);
diff --git a/vcl/inc/vcl/graphite_layout.hxx b/vcl/inc/vcl/graphite_layout.hxx
index 1fbb11211ca0..520f4620cd90 100644
--- a/vcl/inc/vcl/graphite_layout.hxx
+++ b/vcl/inc/vcl/graphite_layout.hxx
@@ -75,6 +75,14 @@ namespace grutils { class GrFeatureParser; }
class VCL_DLLPUBLIC GraphiteLayout : public SalLayout
{
public:
+ // Mask to allow Word break status to be stored within mvChar2BaseGlyph
+ enum {
+ WORD_BREAK_BEFORE = 0x40000000,
+ HYPHEN_BREAK_BEFORE = 0x80000000,
+ BREAK_MASK = 0xC0000000,
+ GLYPH_INDEX_MASK = 0x3FFFFFFF
+ } LineBreakMask;
+
class Glyphs : public std::vector<GlyphItem>
{
public:
@@ -159,6 +167,7 @@ private:
std::pair<int,int> glyph_to_chars(const GlyphItem &) const;
std::pair<long,long> caret_positions(size_t) const;
+ void expandOrCondense(ImplLayoutArgs &rArgs);
};
diff --git a/vcl/source/glyphs/graphite_layout.cxx b/vcl/source/glyphs/graphite_layout.cxx
index 6e75d1fde868..ff2fd8f306b1 100644
--- a/vcl/source/glyphs/graphite_layout.cxx
+++ b/vcl/source/glyphs/graphite_layout.cxx
@@ -353,6 +353,46 @@ std::pair<float,float> GraphiteLayout::Glyphs::appendCluster(gr::Segment & rSeg,
assert(size() < rGlyph2Char.size());
rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] = size();
rGlyph2Char[size()] = nFirstCharInCluster;
+
+ // can we break before this cluster?
+ // Glyphs may have either a positive or negative breakWeight refering to
+ // the position after or before the glyph respectively
+ int nPrevBreakWeight = 0;
+ if (nFirstGlyphInCluster > 0)
+ {
+ nPrevBreakWeight = (iGlyphs.first + (nFirstGlyphInCluster - 1))->breakweight();
+ }
+ int nBreakWeight = aFirstGlyph.breakweight();
+ if (nBreakWeight < 0)
+ {
+ // negative means it applies to the position before the glyph's character
+ nBreakWeight *= -1;
+ if (nPrevBreakWeight > 0 && nPrevBreakWeight < nBreakWeight)
+ {
+ // prevBreakWeight wins
+ nBreakWeight = nPrevBreakWeight;
+ }
+ }
+ else
+ {
+ nBreakWeight = 0;
+ // positive means break after
+ if (nPrevBreakWeight > 0)
+ nBreakWeight = nPrevBreakWeight;
+ }
+ if (nBreakWeight > gr::klbNoBreak/*0*/ &&
+ // nBreakWeight <= gr::klbHyphenBreak) // uses Graphite hyphenation
+ nBreakWeight <= gr::klbLetterBreak) // Needed for issue 111272
+ {
+ if (nBreakWeight < gr::klbHyphenBreak)
+ rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] |= WORD_BREAK_BEFORE;
+ else
+ rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] |= HYPHEN_BREAK_BEFORE;
+ }
+ // always allow a break before a space even if graphite doesn't
+ if (rArgs.mpStr[nFirstCharInCluster] == 0x20)
+ rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] |= WORD_BREAK_BEFORE;
+
bool bBaseGlyph = true;
for (int j = nFirstGlyphInCluster;
j != nNextGlyph; j += nDelta)
@@ -409,7 +449,7 @@ std::pair<float,float> GraphiteLayout::Glyphs::appendCluster(gr::Segment & rSeg,
}
}
#ifdef GRLAYOUT_DEBUG
- fprintf(grLog(),"Cluster g[%d-%d) c[%d-%d)%x x%ld y%f\n", nFirstGlyphInCluster, nNextGlyph, nFirstCharInCluster, nNextChar, rArgs.mpStr[nFirstCharInCluster], nXPos, aFirstGlyph.yOffset());
+ fprintf(grLog(),"Cluster g[%d-%d) c[%d-%d)%x x%ld y%f bw%d\n", nFirstGlyphInCluster, nNextGlyph, nFirstCharInCluster, nNextChar, rArgs.mpStr[nFirstCharInCluster], nXPos, aFirstGlyph.yOffset(), nBreakWeight);
#endif
return aBounds;
}
@@ -641,6 +681,19 @@ gr::Segment * GraphiteLayout::CreateSegment(ImplLayoutArgs& rArgs)
if (bRtl && (mrFont.getSupportedScriptDirections() & gr::kfsdcHorizRtl))
maLayout.setRightToLeft(bRtl);
+ // Context is often needed beyond the specified end, however, we don't
+ // want it if there has been a direction change, since it is hard
+ // to tell between reordering within one direction and multi-directional
+ // text. Extra context, can also cause problems with ligatures stradling
+ // a hyphenation point, so disable if CTL is disabled.
+ const int nSegCharLimit = min(rArgs.mnLength, mnEndCharPos + EXTRA_CONTEXT_LENGTH);
+ int limit = rArgs.mnEndCharPos;
+ if ((nSegCharLimit > limit) && !(SAL_LAYOUT_COMPLEX_DISABLED & rArgs.mnFlags))
+ {
+ limit += findSameDirLimit(rArgs.mpStr + rArgs.mnEndCharPos,
+ nSegCharLimit - rArgs.mnEndCharPos, bRtl);
+ }
+
#ifdef GRCACHE
GrFontHasher hasher(mrFont);
sal_Int32 aFontHash = hasher.hashCode(mpFeatures);
@@ -648,7 +701,7 @@ gr::Segment * GraphiteLayout::CreateSegment(ImplLayoutArgs& rArgs)
(GraphiteCacheHandler::instance).getCache(aFontHash);
if (pCache)
{
- *pSegRecord = pCache->getSegment(rArgs, bRtl);
+ *pSegRecord = pCache->getSegment(rArgs, bRtl, nSegCharLimit);
if (*pSegRecord)
{
pSegment = (*pSegRecord)->getSegment();
@@ -667,18 +720,6 @@ gr::Segment * GraphiteLayout::CreateSegment(ImplLayoutArgs& rArgs)
}
#endif
- // Context is often needed beyond the specified end, however, we don't
- // want it if there has been a direction change, since it is hard
- // to tell between reordering within one direction and multi-directional
- // text.
- const int segCharLimit = min(rArgs.mnLength, mnEndCharPos + EXTRA_CONTEXT_LENGTH);
- int limit = rArgs.mnEndCharPos;
- if (segCharLimit > limit)
- {
- limit += findSameDirLimit(rArgs.mpStr + rArgs.mnEndCharPos,
- segCharLimit - rArgs.mnEndCharPos, bRtl);
- }
-
// Create a new TextSource object for the engine.
mpTextSrc = new TextSourceAdaptor(rArgs, limit);
if (mpFeatures) mpTextSrc->setFeatures(mpFeatures);
@@ -795,27 +836,35 @@ bool GraphiteLayout::LayoutGlyphs(ImplLayoutArgs& rArgs, gr::Segment * pSegment)
int GraphiteLayout::GetTextBreak(long maxmnWidth, long char_extra, int factor) const
{
- // Adjust maxmnWidth so FindNextBreakPoint returns a sensible answer.
- maxmnWidth -= (mnEndCharPos-mnMinCharPos-1)*char_extra; // extra character spacing.
- maxmnWidth /= factor; // scaling factor.
+#ifdef GRLAYOUT_DEBUG
+ fprintf(grLog(),"Gr::GetTextBreak c[%d-%d) maxWidth %ld char extra %ld factor %d\n",
+ mnMinCharPos, mnEndCharPos, maxmnWidth, char_extra, factor);
+#endif
- // Ask the segment for the nearest whole letter break for the width.
- //float width;
- float targetWidth = maxmnWidth/mfScaling;
// return quickly if this segment is narrower than the target width
- // (sometimes graphite doesn't seem to realise this!)
- if (targetWidth > mnWidth)
+ if (maxmnWidth > mnWidth * factor + char_extra * (mnEndCharPos - mnMinCharPos - 1))
return STRING_LEN;
- //int nBreak = mpSegment->findNextBreakPoint(mnMinCharPos,
- // gr::klbWordBreak, gr::klbLetterBreak, targetWidth, &width);
- // LineFillSegment seems to give better results that findNextBreakPoint
- // though it may be slower
- gr::LayoutEnvironment aLE;
- gr::LineFillSegment lineSeg(const_cast<gr::Font *>(&mrFont), mpTextSrc, &aLE,
- mnMinCharPos, mpTextSrc->getContextLength(),
- targetWidth);
- int nBreak = lineSeg.stopCharacter();
+ long nWidth = mvCharDxs[0] * factor;
+ int nLastBreak = -1;
+ for (size_t i = 1; i < mvCharDxs.size(); i++)
+ {
+ nWidth += char_extra;
+ if (nWidth > maxmnWidth) break;
+ if (mvChar2BaseGlyph[i] != -1)
+ {
+ if (mvChar2BaseGlyph[i] & (WORD_BREAK_BEFORE | HYPHEN_BREAK_BEFORE))
+ nLastBreak = static_cast<int>(i);
+ }
+ nWidth += (mvCharDxs[i] - mvCharDxs[i-1]) * factor;
+ }
+ int nBreak = mnMinCharPos;
+ if (nLastBreak > -1)
+ nBreak += nLastBreak;
+
+#ifdef GRLAYOUT_DEBUG
+ fprintf(grLog(), "Gr::GetTextBreak break after %d\n", nBreak - mnMinCharPos);
+#endif
if (nBreak > mnEndCharPos) nBreak = STRING_LEN;
else if (nBreak < mnMinCharPos) nBreak = mnMinCharPos;
@@ -833,9 +882,10 @@ long GraphiteLayout::FillDXArray( sal_Int32* pDXArray ) const
{
for (size_t i = 0; i < mvCharDxs.size(); i++)
{
- assert((mvChar2BaseGlyph[i] >= -1) && (mvChar2BaseGlyph[i] < (signed)mvGlyphs.size()));
+ assert( (mvChar2BaseGlyph[i] == -1) ||
+ ((signed)(mvChar2BaseGlyph[i] & GLYPH_INDEX_MASK) < (signed)mvGlyphs.size()));
if (mvChar2BaseGlyph[i] != -1 &&
- mvGlyphs[mvChar2BaseGlyph[i]].mnGlyphIndex == GF_DROPPED)
+ mvGlyphs[mvChar2BaseGlyph[i] & GLYPH_INDEX_MASK].mnGlyphIndex == GF_DROPPED)
{
// when used in MultiSalLayout::GetTextBreak dropped glyphs
// must have zero width
@@ -865,7 +915,6 @@ long GraphiteLayout::FillDXArray( sal_Int32* pDXArray ) const
void GraphiteLayout::AdjustLayout(ImplLayoutArgs& rArgs)
{
SalLayout::AdjustLayout(rArgs);
-
if(rArgs.mpDXArray)
{
std::vector<int> vDeltaWidths(mvGlyphs.size(), 0);
@@ -894,8 +943,75 @@ void GraphiteLayout::AdjustLayout(ImplLayoutArgs& rArgs)
}
}
}
+ else if (rArgs.mnLayoutWidth > 0)
+ {
+#ifdef GRLAYOUT_DEBUG
+ fprintf(grLog(), "AdjustLayout width %ld=>%ld\n", mnWidth, rArgs.mnLayoutWidth);
+#endif
+ expandOrCondense(rArgs);
+ }
}
+void GraphiteLayout::expandOrCondense(ImplLayoutArgs &rArgs)
+{
+ int nDeltaWidth = rArgs.mnLayoutWidth - mnWidth;
+ if (nDeltaWidth > 0) // expand, just expand between clusters
+ {
+ int nClusterCount = 0;
+ for (size_t j = 0; j < mvGlyphs.size(); j++)
+ {
+ if (mvGlyphs[j].IsClusterStart())
+ {
+ ++nClusterCount;
+ }
+ }
+ if (nClusterCount > 1)
+ {
+ float fExtraPerCluster = static_cast<float>(nDeltaWidth) / static_cast<float>(nClusterCount - 1);
+ int nCluster = 0;
+ int nOffset = 0;
+ for (size_t i = 0; i < mvGlyphs.size(); i++)
+ {
+ if (mvGlyphs[i].IsClusterStart())
+ {
+ nOffset = fExtraPerCluster * nCluster;
+ size_t nCharIndex = mvGlyph2Char[i];
+ mvCharDxs[nCharIndex] += nOffset;
+ // adjust char dxs for rest of characters in cluster
+ while (++nCharIndex < mvGlyph2Char.size())
+ {
+ int nChar2Base = (mvChar2BaseGlyph[nCharIndex] == -1)? -1 : mvChar2BaseGlyph[nCharIndex] & GLYPH_INDEX_MASK;
+ if (nChar2Base == -1 || nChar2Base == static_cast<int>(i))
+ mvCharDxs[nCharIndex] += nOffset;
+ }
+ ++nCluster;
+ }
+ mvGlyphs[i].maLinearPos.X() += nOffset;
+ }
+ }
+ }
+ else // condense - apply a factor to all glyph positions
+ {
+ if (mvGlyphs.size() == 0) return;
+ Glyphs::iterator iLastGlyph = mvGlyphs.begin() + (mvGlyphs.size() - 1);
+ // position last glyph using original width
+ float fXFactor = static_cast<float>(rArgs.mnLayoutWidth - iLastGlyph->mnOrigWidth) / static_cast<float>(iLastGlyph->maLinearPos.X());
+#ifdef GRLAYOUT_DEBUG
+ fprintf(grLog(), "Condense by factor %f\n", fXFactor);
+#endif
+ iLastGlyph->maLinearPos.X() = rArgs.mnLayoutWidth - iLastGlyph->mnOrigWidth;
+ Glyphs::iterator iGlyph = mvGlyphs.begin();
+ while (iGlyph != iLastGlyph)
+ {
+ iGlyph->maLinearPos.X() = static_cast<float>(iGlyph->maLinearPos.X()) * fXFactor;
+ ++iGlyph;
+ }
+ for (size_t i = 0; i < mvCharDxs.size(); i++)
+ {
+ mvCharDxs[i] = fXFactor * static_cast<float>(mvCharDxs[i]);
+ }
+ }
+}
void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDeltaWidth)
{
@@ -917,37 +1033,39 @@ void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDelt
int nPrevClusterLastChar = -1;
for (size_t i = 0; i < nChars; i++)
{
- if (mvChar2BaseGlyph[i] > -1 && mvChar2BaseGlyph[i] != nPrevClusterGlyph)
+ int nChar2Base = (mvChar2BaseGlyph[i] == -1)? -1 : mvChar2BaseGlyph[i] & GLYPH_INDEX_MASK;
+ if ((nChar2Base > -1) && (nChar2Base != nPrevClusterGlyph))
{
- assert((mvChar2BaseGlyph[i] > -1) && (mvChar2BaseGlyph[i] < (signed)mvGlyphs.size()));
- GlyphItem & gi = mvGlyphs[mvChar2BaseGlyph[i]];
+ assert((nChar2Base > -1) && (nChar2Base < (signed)mvGlyphs.size()));
+ GlyphItem & gi = mvGlyphs[nChar2Base];
if (!gi.IsClusterStart())
continue;
// find last glyph of this cluster
size_t j = i + 1;
int nLastChar = i;
- int nLastGlyph = mvChar2BaseGlyph[i];
+ int nLastGlyph = nChar2Base;
for (; j < nChars; j++)
{
- assert((mvChar2BaseGlyph[j] >= -1) && (mvChar2BaseGlyph[j] < (signed)mvGlyphs.size()));
- if (mvChar2BaseGlyph[j] != -1 && mvGlyphs[mvChar2BaseGlyph[j]].IsClusterStart())
+ int nChar2BaseJ = (mvChar2BaseGlyph[j] == -1)? -1 : mvChar2BaseGlyph[j] & GLYPH_INDEX_MASK;
+ assert((nChar2BaseJ >= -1) && (nChar2BaseJ < (signed)mvGlyphs.size()));
+ if (nChar2BaseJ != -1 && mvGlyphs[nChar2BaseJ].IsClusterStart())
{
- nLastGlyph = mvChar2BaseGlyph[j] + ((bRtl)? 1 : -1);
+ nLastGlyph = nChar2BaseJ + ((bRtl)? 1 : -1);
nLastChar = j - 1;
break;
}
}
if (nLastGlyph < 0)
{
- nLastGlyph = mvChar2BaseGlyph[i];
+ nLastGlyph = nChar2Base;
}
// Its harder to find the last glyph rtl, since the first of
// cluster is still on the left so we need to search towards
// the previous cluster to the right
if (bRtl)
{
- nLastGlyph = mvChar2BaseGlyph[i];
+ nLastGlyph = nChar2Base;
while (nLastGlyph + 1 < (signed)mvGlyphs.size() &&
!mvGlyphs[nLastGlyph+1].IsClusterStart())
{
@@ -983,7 +1101,7 @@ void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDelt
// update glyph positions
if (bRtl)
{
- for (int n = mvChar2BaseGlyph[i]; n <= nLastGlyph; n++)
+ for (int n = nChar2Base; n <= nLastGlyph; n++)
{
assert((n > - 1) && (n < (signed)mvGlyphs.size()));
mvGlyphs[n].maLinearPos.X() += -nDGlyphOrigin + nXOffset;
@@ -991,17 +1109,17 @@ void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDelt
}
else
{
- for (int n = mvChar2BaseGlyph[i]; n <= nLastGlyph; n++)
+ for (int n = nChar2Base; n <= nLastGlyph; n++)
{
assert((n > - 1) && (n < (signed)mvGlyphs.size()));
mvGlyphs[n].maLinearPos.X() += nDGlyphOrigin + nXOffset;
}
}
- rDeltaWidth[mvChar2BaseGlyph[i]] = nDWidth;
+ rDeltaWidth[nChar2Base] = nDWidth;
#ifdef GRLAYOUT_DEBUG
- fprintf(grLog(),"c%d g%d-%d dW%ld-%ld=%ld dX%ld x%ld\t", (int)i, mvChar2BaseGlyph[i], nLastGlyph, nNewClusterWidth, nOrigClusterWidth, nDWidth, nDGlyphOrigin, mvGlyphs[mvChar2BaseGlyph[i]].maLinearPos.X());
+ fprintf(grLog(),"c%d g%d-%d dW%ld-%ld=%ld dX%ld x%ld\t", (int)i, nChar2Base, nLastGlyph, nNewClusterWidth, nOrigClusterWidth, nDWidth, nDGlyphOrigin, mvGlyphs[nChar2Base].maLinearPos.X());
#endif
- nPrevClusterGlyph = mvChar2BaseGlyph[i];
+ nPrevClusterGlyph = nChar2Base;
nPrevClusterLastChar = nLastChar;
i = nLastChar;
}
@@ -1043,7 +1161,7 @@ void GraphiteLayout::kashidaJustify(std::vector<int>& rDeltaWidths, sal_GlyphId
continue;
}
// calculate gap, ignore if too small
- int nGapWidth = rDeltaWidths[nOrigGlyphIndex];;
+ int nGapWidth = rDeltaWidths[nOrigGlyphIndex];
// worst case is one kashida even for mini-gaps
if( 3 * nGapWidth < nKashidaWidth )
{
@@ -1104,13 +1222,14 @@ void GraphiteLayout::GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray
{
if (mvChar2BaseGlyph[nCharSlot] != -1)
{
- assert((mvChar2BaseGlyph[nCharSlot] > -1) && (mvChar2BaseGlyph[nCharSlot] < (signed)mvGlyphs.size()));
- GlyphItem gi = mvGlyphs[mvChar2BaseGlyph[nCharSlot]];
+ int nChar2Base = mvChar2BaseGlyph[nCharSlot] & GLYPH_INDEX_MASK;
+ assert((mvChar2BaseGlyph[nCharSlot] > -1) && (nChar2Base < (signed)mvGlyphs.size()));
+ GlyphItem gi = mvGlyphs[nChar2Base];
if (gi.mnGlyphIndex == GF_DROPPED)
{
continue;
}
- int nCluster = mvChar2BaseGlyph[nCharSlot];
+ int nCluster = nChar2Base;
long origClusterWidth = gi.mnNewWidth;
long nMin = gi.maLinearPos.X();
long nMax = gi.maLinearPos.X() + gi.mnNewWidth;
@@ -1135,7 +1254,7 @@ void GraphiteLayout::GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray
pCaretXArray[i] = nMin;
pCaretXArray[i+1] = nMax;
}
- prevBase = mvChar2BaseGlyph[nCharSlot];
+ prevBase = nChar2Base;
prevClusterWidth = origClusterWidth;
}
else if (prevBase > -1)
@@ -1268,7 +1387,7 @@ int GraphiteLayout::GetNextGlyphs( int length, sal_GlyphId * glyph_out,
#ifdef GRLAYOUT_DEBUG
fprintf(grLog(),"GetNextGlyphs g%d c%d x%ld,%ld adv%ld, pos %ld,%ld\n", glyph_slot - 1,
- mvGlyph2Char[glyph_slot-1], glyph_itr->maLinearPos.X(), glyph_itr->maLinearPos.Y(), nGlyphAdvance,
+ GLYPH_INDEX_MASK&mvGlyph2Char[glyph_slot-1], glyph_itr->maLinearPos.X(), glyph_itr->maLinearPos.Y(), nGlyphAdvance,
aPosOut.X(), aPosOut.Y());
#endif