|
|
1de50a9 |
From d2ef084eb0e26b5ee18133269249e7a80efb23d6 Mon Sep 17 00:00:00 2001
|
|
|
1de50a9 |
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
|
|
1de50a9 |
Date: Mon, 29 Jun 2015 12:26:16 +0200
|
|
|
1de50a9 |
Subject: [PATCH] update graphite to 1.3.5
|
|
|
1de50a9 |
|
|
|
1de50a9 |
(cherry picked from commit c64ea526dc71da6e3aad188ac71e58047ed74b5a)
|
|
|
1de50a9 |
|
|
|
1de50a9 |
and sync the various upgrade patches together
|
|
|
1de50a9 |
|
|
|
1de50a9 |
Change-Id: I3287d51430d7a0901dd8bbf2458b845bcf92a8d2
|
|
|
1de50a9 |
Reviewed-on: https://gerrit.libreoffice.org/22210
|
|
|
1de50a9 |
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
|
|
|
1de50a9 |
Tested-by: Miklos Vajna <vmiklos@collabora.co.uk>
|
|
|
1de50a9 |
---
|
|
|
1de50a9 |
download.lst | 3 +-
|
|
|
1de50a9 |
editeng/source/editeng/impedit3.cxx | 6 +-
|
|
|
1de50a9 |
external/graphite/StaticLibrary_graphite.mk | 9 +-
|
|
|
1de50a9 |
external/graphite/UnpackedTarball_graphite.mk | 4 +-
|
|
|
1de50a9 |
external/graphite/graphite2.issue1115.patch.1 | 6 +-
|
|
|
1de50a9 |
external/graphite/graphite2.win64.patch.1 | 34 +-
|
|
|
1de50a9 |
external/graphite/ubsan.patch | 51 ++
|
|
|
1de50a9 |
vcl/inc/graphite_layout.hxx | 10 +-
|
|
|
1de50a9 |
vcl/source/fontsubset/sft.cxx | 3 +
|
|
|
1de50a9 |
vcl/source/gdi/pdfwriter_impl.cxx | 15 +-
|
|
|
1de50a9 |
vcl/source/glyphs/graphite_layout.cxx | 799 +++++++++-----------------
|
|
|
1de50a9 |
vcl/win/source/gdi/winlayout.cxx | 15 +-
|
|
|
1de50a9 |
12 files changed, 396 insertions(+), 559 deletions(-)
|
|
|
1de50a9 |
create mode 100644 external/graphite/ubsan.patch
|
|
|
1de50a9 |
|
|
|
1de50a9 |
diff --git a/download.lst b/download.lst
|
|
|
1de50a9 |
index bc94112..9e16272 100644
|
|
|
1de50a9 |
--- a/download.lst
|
|
|
1de50a9 |
+++ b/download.lst
|
|
|
1de50a9 |
@@ -59,8 +59,7 @@ export FREEHAND_TARBALL := libfreehand-0.1.1.tar.bz2
|
|
|
1de50a9 |
export FREETYPE_TARBALL := dbf2caca1d3afd410a29217a9809d397-freetype-2.4.8.tar.bz2
|
|
|
1de50a9 |
export GLEW_TARBALL := 594eb47b4b1210e25438d51825404d5a-glew-1.10.0.zip
|
|
|
1de50a9 |
export GLM_TARBALL := bae83fa5dc7f081768daace6e199adc3-glm-0.9.4.6-libreoffice.zip
|
|
|
1de50a9 |
-export GRAPHITE_MD5SUM := 2ef839348fe28e3b923bf8cced440227
|
|
|
1de50a9 |
-export GRAPHITE_TARBALL := graphite2-1.2.4.tgz
|
|
|
1de50a9 |
+export GRAPHITE_TARBALL := 28935e208c311761c29983c739db08d8-graphite2-minimal-1.3.5.tgz
|
|
|
1de50a9 |
export HARFBUZZ_MD5SUM := 0e27e531f4c4acff601ebff0957755c2
|
|
|
1de50a9 |
export HARFBUZZ_TARBALL := harfbuzz-0.9.40.tar.bz2
|
|
|
1de50a9 |
export HSQLDB_TARBALL := 17410483b5b5f267aa18b7e00b65e6e0-hsqldb_1_8_0.zip
|
|
|
1de50a9 |
diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx
|
|
|
1de50a9 |
index 98e3d51..5df7e5e 100644
|
|
|
1de50a9 |
--- a/editeng/source/editeng/impedit3.cxx
|
|
|
1de50a9 |
+++ b/editeng/source/editeng/impedit3.cxx
|
|
|
1de50a9 |
@@ -714,6 +714,8 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
|
|
|
1de50a9 |
EditLine aSaveLine( *pLine );
|
|
|
1de50a9 |
SvxFont aTmpFont( pNode->GetCharAttribs().GetDefFont() );
|
|
|
1de50a9 |
|
|
|
1de50a9 |
+ ImplInitLayoutMode( GetRefDevice(), nPara, nIndex );
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
bool bCalcCharPositions = true;
|
|
|
1de50a9 |
boost::scoped_array<long> pBuf(new long[ pNode->Len() ]);
|
|
|
1de50a9 |
|
|
|
1de50a9 |
@@ -1038,6 +1040,8 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
|
|
|
1de50a9 |
aTmpFont.SetPhysFont( GetRefDevice() );
|
|
|
1de50a9 |
ImplInitDigitMode(GetRefDevice(), aTmpFont.GetLanguage());
|
|
|
1de50a9 |
|
|
|
1de50a9 |
+ pPortion->SetRightToLeft( GetRightToLeft( nPara, nTmpPos+1 ) );
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
if ( bCalcCharPositions || !pPortion->HasValidSize() )
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
pPortion->GetSize() = aTmpFont.QuickGetTextSize( GetRefDevice(), pParaPortion->GetNode()->GetString(), nTmpPos, pPortion->GetLen(), pBuf.get() );
|
|
|
1de50a9 |
@@ -1069,8 +1073,6 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
|
|
|
1de50a9 |
|
|
|
1de50a9 |
nTmpWidth += pPortion->GetSize().Width();
|
|
|
1de50a9 |
|
|
|
1de50a9 |
- pPortion->SetRightToLeft( GetRightToLeft( nPara, nTmpPos+1 ) );
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
sal_Int32 _nPortionEnd = nTmpPos + pPortion->GetLen();
|
|
|
1de50a9 |
if( bScriptSpace && ( _nPortionEnd < pNode->Len() ) && ( nTmpWidth < nXWidth ) && IsScriptChange( EditPaM( pNode, _nPortionEnd ) ) )
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
diff --git a/external/graphite/StaticLibrary_graphite.mk b/external/graphite/StaticLibrary_graphite.mk
|
|
|
1de50a9 |
index de3950f..ddbf995 100644
|
|
|
1de50a9 |
--- a/external/graphite/StaticLibrary_graphite.mk
|
|
|
1de50a9 |
+++ b/external/graphite/StaticLibrary_graphite.mk
|
|
|
1de50a9 |
@@ -19,8 +19,8 @@ $(eval $(call gb_StaticLibrary_set_include,graphite,\
|
|
|
1de50a9 |
))
|
|
|
1de50a9 |
|
|
|
1de50a9 |
$(eval $(call gb_StaticLibrary_add_defs,graphite,\
|
|
|
1de50a9 |
- -DDISABLE_TRACING \
|
|
|
1de50a9 |
- -DGR2_STATIC \
|
|
|
1de50a9 |
+ -DGRAPHITE2_NTRACING \
|
|
|
1de50a9 |
+ -DGRAPHITE2_STATIC \
|
|
|
1de50a9 |
))
|
|
|
1de50a9 |
|
|
|
1de50a9 |
ifeq ($(COM),GCC)
|
|
|
1de50a9 |
@@ -43,19 +43,22 @@ $(eval $(call gb_StaticLibrary_add_generated_cxxobjects,graphite,\
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/gr_segment \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/gr_slot \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/json \
|
|
|
1de50a9 |
- UnpackedTarball/graphite/src/Bidi \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/CachedFace \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/CmapCache \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/Code \
|
|
|
1de50a9 |
+ UnpackedTarball/graphite/src/Collider \
|
|
|
1de50a9 |
+ UnpackedTarball/graphite/src/Decompressor \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/Face \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/FeatureMap \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/FileFace \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/Font \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/GlyphCache \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/GlyphFace \
|
|
|
1de50a9 |
+ UnpackedTarball/graphite/src/Intervals \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/Justifier \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/NameTable \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/Pass \
|
|
|
1de50a9 |
+ UnpackedTarball/graphite/src/Position \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/SegCache \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/SegCacheEntry \
|
|
|
1de50a9 |
UnpackedTarball/graphite/src/SegCacheStore \
|
|
|
1de50a9 |
diff --git a/external/graphite/UnpackedTarball_graphite.mk b/external/graphite/UnpackedTarball_graphite.mk
|
|
|
1de50a9 |
index c7fa86e..a162d17 100644
|
|
|
1de50a9 |
--- a/external/graphite/UnpackedTarball_graphite.mk
|
|
|
1de50a9 |
+++ b/external/graphite/UnpackedTarball_graphite.mk
|
|
|
1de50a9 |
@@ -11,10 +11,12 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,graphite))
|
|
|
1de50a9 |
|
|
|
1de50a9 |
$(eval $(call gb_UnpackedTarball_set_tarball,graphite,$(GRAPHITE_TARBALL)))
|
|
|
1de50a9 |
|
|
|
1de50a9 |
-# http://projects.palaso.org/issues/1115
|
|
|
1de50a9 |
+$(eval $(call gb_UnpackedTarball_set_patchlevel,graphite,0))
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
$(eval $(call gb_UnpackedTarball_add_patches,graphite,\
|
|
|
1de50a9 |
external/graphite/graphite2.issue1115.patch.1 \
|
|
|
1de50a9 |
external/graphite/graphite2.win64.patch.1 \
|
|
|
1de50a9 |
+ external/graphite/ubsan.patch \
|
|
|
1de50a9 |
))
|
|
|
1de50a9 |
|
|
|
1de50a9 |
# vim: set noet sw=4 ts=4:
|
|
|
1de50a9 |
diff --git a/external/graphite/graphite2.issue1115.patch.1 b/external/graphite/graphite2.issue1115.patch.1
|
|
|
1de50a9 |
index f19c8a3..454114b 100644
|
|
|
1de50a9 |
--- a/external/graphite/graphite2.issue1115.patch.1
|
|
|
1de50a9 |
+++ b/external/graphite/graphite2.issue1115.patch.1
|
|
|
1de50a9 |
@@ -1,6 +1,6 @@
|
|
|
1de50a9 |
--- graphite/src/Code.cpp
|
|
|
1de50a9 |
+++ graphite/src/Code.cpp
|
|
|
1de50a9 |
-@@ -169,8 +169,8 @@ Machine::Code::Code(bool is_constraint,
|
|
|
1de50a9 |
+@@ -175,8 +175,8 @@ Machine::Code::Code(bool is_constraint,
|
|
|
1de50a9 |
bytecode_end,
|
|
|
1de50a9 |
pre_context,
|
|
|
1de50a9 |
rule_length,
|
|
|
1de50a9 |
@@ -11,7 +11,7 @@
|
|
|
1de50a9 |
face.numFeatures(),
|
|
|
1de50a9 |
{1,1,1,1,1,1,1,1,
|
|
|
1de50a9 |
1,1,1,1,1,1,1,255,
|
|
|
1de50a9 |
-@@ -178,7 +178,7 @@ Machine::Code::Code(bool is_constraint,
|
|
|
1de50a9 |
+@@ -184,7 +184,7 @@ Machine::Code::Code(bool is_constraint,
|
|
|
1de50a9 |
1,1,1,1,1,1,0,0,
|
|
|
1de50a9 |
0,0,0,0,0,0,0,0,
|
|
|
1de50a9 |
0,0,0,0,0,0,0,0,
|
|
|
1de50a9 |
@@ -19,4 +19,4 @@
|
|
|
1de50a9 |
+ 0,0,0,0,0,0,0, static_cast<byte>(silf.numUser())}
|
|
|
1de50a9 |
};
|
|
|
1de50a9 |
|
|
|
1de50a9 |
- decoder dec(lims, *this);
|
|
|
1de50a9 |
+ decoder dec(lims, *this, pt);
|
|
|
1de50a9 |
diff --git a/external/graphite/graphite2.win64.patch.1 b/external/graphite/graphite2.win64.patch.1
|
|
|
1de50a9 |
index 6bf8c88..e7c36c6 100644
|
|
|
1de50a9 |
--- a/external/graphite/graphite2.win64.patch.1
|
|
|
1de50a9 |
+++ b/external/graphite/graphite2.win64.patch.1
|
|
|
1de50a9 |
@@ -1,7 +1,20 @@
|
|
|
1de50a9 |
+diff -ur graphite.org/src/inc/Main.h graphite/src/inc/Main.h
|
|
|
1de50a9 |
+--- graphite.org/src/inc/Main.h 2015-09-07 20:09:25.572279671 +0700
|
|
|
1de50a9 |
+--- graphite/src/inc/Main.h 2015-09-07 20:09:25.572279671 +0700
|
|
|
1de50a9 |
+@@ -25,6 +25,9 @@
|
|
|
1de50a9 |
+ of the License or (at your option) any later version.
|
|
|
1de50a9 |
+ */
|
|
|
1de50a9 |
+ #pragma once
|
|
|
1de50a9 |
++#ifdef _WIN32
|
|
|
1de50a9 |
++#pragma warning(disable: 4510 4610)
|
|
|
1de50a9 |
++#endif
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ #include <cstdlib>
|
|
|
1de50a9 |
+ #include "graphite2/Types.h"
|
|
|
1de50a9 |
diff -ur graphite.org/src/inc/json.h graphite/src/inc/json.h
|
|
|
1de50a9 |
--- graphite.org/src/inc/json.h 2015-02-03 14:49:24.408101900 +0100
|
|
|
1de50a9 |
+++ graphite/src/inc/json.h 2015-02-03 14:50:59.697552200 +0100
|
|
|
1de50a9 |
-@@ -78,6 +78,9 @@
|
|
|
1de50a9 |
+@@ -85,6 +85,9 @@
|
|
|
1de50a9 |
json & operator << (string) throw();
|
|
|
1de50a9 |
json & operator << (number) throw();
|
|
|
1de50a9 |
json & operator << (integer) throw();
|
|
|
1de50a9 |
@@ -14,8 +27,7 @@ diff -ur graphite.org/src/inc/json.h graphite/src/inc/json.h
|
|
|
1de50a9 |
diff -ur graphite.org/src/json.cpp graphite/src/json.cpp
|
|
|
1de50a9 |
--- graphite.org/src/json.cpp 2015-02-03 14:49:24.409102000 +0100
|
|
|
1de50a9 |
+++ graphite/src/json.cpp 2015-02-03 14:50:49.814986900 +0100
|
|
|
1de50a9 |
-@@ -119,6 +119,9 @@
|
|
|
1de50a9 |
- json & json::operator << (json::number f) throw() { context(seq); fprintf(_stream, "%g", f); return *this; }
|
|
|
1de50a9 |
+@@ -134,5 +134,8 @@
|
|
|
1de50a9 |
json & json::operator << (json::integer d) throw() { context(seq); fprintf(_stream, "%ld", d); return *this; }
|
|
|
1de50a9 |
json & json::operator << (long unsigned d) throw() { context(seq); fprintf(_stream, "%ld", d); return *this; }
|
|
|
1de50a9 |
+#ifdef _WIN64
|
|
|
1de50a9 |
@@ -27,17 +39,17 @@ diff -ur graphite.org/src/json.cpp graphite/src/json.cpp
|
|
|
1de50a9 |
diff -ur graphite.org/src/Pass.cpp graphite/src/Pass.cpp
|
|
|
1de50a9 |
--- graphite.org/src/Pass.cpp 2015-02-03 14:49:24.413102200 +0100
|
|
|
1de50a9 |
+++ graphite/src/Pass.cpp 2015-02-03 14:50:37.873303900 +0100
|
|
|
1de50a9 |
-@@ -466,7 +466,7 @@
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- if (r->rule->preContext > fsm.slots.context()) continue;
|
|
|
1de50a9 |
- *fsm.dbgout << json::flat << json::object
|
|
|
1de50a9 |
-- << "id" << r->rule - m_rules
|
|
|
1de50a9 |
-+ << "id" << static_cast<size_t>(r->rule - m_rules)
|
|
|
1de50a9 |
+@@ -544,7 +544,7 @@
|
|
|
1de50a9 |
+ if (r->rule->preContext > fsm.slots.context())
|
|
|
1de50a9 |
+ continue;
|
|
|
1de50a9 |
+ *fsm.dbgout << json::flat << json::object
|
|
|
1de50a9 |
+- << "id" << r->rule - m_rules
|
|
|
1de50a9 |
++ << "id" << static_cast<size_t>(r->rule - m_rules)
|
|
|
1de50a9 |
<< "failed" << true
|
|
|
1de50a9 |
<< "input" << json::flat << json::object
|
|
|
1de50a9 |
<< "start" << objectid(dslot(&fsm.slots.segment, input_slot(fsm.slots, -r->rule->preContext)))
|
|
|
1de50a9 |
-@@ -480,7 +480,7 @@
|
|
|
1de50a9 |
- void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * const last_slot) const
|
|
|
1de50a9 |
+@@ -558,7 +558,7 @@
|
|
|
1de50a9 |
+ void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, Machine & m, const Rule & r, Slot * const last_slot) const
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
*fsm.dbgout << json::item << json::flat << json::object
|
|
|
1de50a9 |
- << "id" << &r - m_rules
|
|
|
1de50a9 |
diff --git a/external/graphite/ubsan.patch b/external/graphite/ubsan.patch
|
|
|
1de50a9 |
new file mode 100644
|
|
|
1de50a9 |
index 0000000..b1617b1
|
|
|
1de50a9 |
--- /dev/null
|
|
|
1de50a9 |
+++ b/external/graphite/ubsan.patch
|
|
|
1de50a9 |
@@ -0,0 +1,51 @@
|
|
|
1de50a9 |
+--- src/Pass.cpp
|
|
|
1de50a9 |
++++ src/Pass.cpp
|
|
|
1de50a9 |
+@@ -294,7 +294,7 @@
|
|
|
1de50a9 |
+ s->rules = begin;
|
|
|
1de50a9 |
+ s->rules_end = (end - begin <= FiniteStateMachine::MAX_RULES)? end :
|
|
|
1de50a9 |
+ begin + FiniteStateMachine::MAX_RULES;
|
|
|
1de50a9 |
+- qsort(begin, end - begin, sizeof(RuleEntry), &cmpRuleEntry);
|
|
|
1de50a9 |
++ if (end != begin) qsort(begin, end - begin, sizeof(RuleEntry), &cmpRuleEntry);
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ return true;
|
|
|
1de50a9 |
+--- src/gr_face.cpp
|
|
|
1de50a9 |
++++ src/gr_face.cpp
|
|
|
1de50a9 |
+@@ -87,7 +87,7 @@
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ Face *res = new Face(appFaceHandle, *ops);
|
|
|
1de50a9 |
+ if (res && load_face(*res, faceOptions))
|
|
|
1de50a9 |
+- return static_cast<gr_face *>(res);
|
|
|
1de50a9 |
++ return reinterpret_cast<gr_face *>(res);
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ delete res;
|
|
|
1de50a9 |
+ return 0;
|
|
|
1de50a9 |
+@@ -195,7 +195,7 @@
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ void gr_face_destroy(gr_face *face)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+- delete face;
|
|
|
1de50a9 |
++ delete static_cast<Face *>(face);
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+--- src/gr_font.cpp
|
|
|
1de50a9 |
++++ src/gr_font.cpp
|
|
|
1de50a9 |
+@@ -50,7 +50,7 @@
|
|
|
1de50a9 |
+ if (face == 0) return 0;
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ Font * const res = new Font(ppm, *face, appFontHandle, font_ops);
|
|
|
1de50a9 |
+- return static_cast<gr_font*>(res);
|
|
|
1de50a9 |
++ return reinterpret_cast<gr_font*>(res);
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ gr_font* gr_make_font_with_advance_fn(float ppm/*pixels per em*/, const void* appFontHandle/*non-NULL*/, gr_advance_fn getAdvance, const gr_face * face/*needed for scaling*/)
|
|
|
1de50a9 |
+@@ -61,7 +61,7 @@
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ void gr_font_destroy(gr_font *font)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+- delete font;
|
|
|
1de50a9 |
++ delete static_cast<Font *>(font);
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
diff --git a/vcl/inc/graphite_layout.hxx b/vcl/inc/graphite_layout.hxx
|
|
|
1de50a9 |
index 55d0d67..b97b351 100644
|
|
|
1de50a9 |
--- a/vcl/inc/graphite_layout.hxx
|
|
|
1de50a9 |
+++ b/vcl/inc/graphite_layout.hxx
|
|
|
1de50a9 |
@@ -93,9 +93,10 @@ public:
|
|
|
1de50a9 |
private:
|
|
|
1de50a9 |
const gr_face * mpFace; // not owned by layout
|
|
|
1de50a9 |
gr_font * mpFont; // not owned by layout
|
|
|
1de50a9 |
- int mnSegCharOffset; // relative to ImplLayoutArgs::mpStr
|
|
|
1de50a9 |
+ unsigned int mnSegCharOffset; // relative to ImplLayoutArgs::mpStr
|
|
|
1de50a9 |
long mnWidth;
|
|
|
1de50a9 |
std::vector<int> mvChar2BaseGlyph;
|
|
|
1de50a9 |
+ std::vector<int> mvChar2Glyph;
|
|
|
1de50a9 |
std::vector<int> mvGlyph2Char;
|
|
|
1de50a9 |
std::vector<int> mvCharDxs;
|
|
|
1de50a9 |
std::vector<int> mvCharBreaks;
|
|
|
1de50a9 |
@@ -109,8 +110,6 @@ public:
|
|
|
1de50a9 |
// used by upper layers
|
|
|
1de50a9 |
virtual bool LayoutText( ImplLayoutArgs& ) SAL_OVERRIDE; // first step of layout
|
|
|
1de50a9 |
// split into two stages to allow dc to be restored on the segment
|
|
|
1de50a9 |
- gr_segment * CreateSegment(ImplLayoutArgs& rArgs);
|
|
|
1de50a9 |
- bool LayoutGlyphs(ImplLayoutArgs& rArgs, gr_segment * pSegment);
|
|
|
1de50a9 |
|
|
|
1de50a9 |
virtual void AdjustLayout( ImplLayoutArgs& ) SAL_OVERRIDE; // adjusting positions
|
|
|
1de50a9 |
|
|
|
1de50a9 |
@@ -145,13 +144,14 @@ public:
|
|
|
1de50a9 |
static const int EXTRA_CONTEXT_LENGTH;
|
|
|
1de50a9 |
private:
|
|
|
1de50a9 |
void expandOrCondense(ImplLayoutArgs &rArgs);
|
|
|
1de50a9 |
- void fillFrom(gr_segment * rSeg, ImplLayoutArgs & rArgs, float fScaling);
|
|
|
1de50a9 |
+ void fillFrom(gr_segment * rSeg, ImplLayoutArgs & rArgs, float fScaling, bool bRtl, int firstCharOffset);
|
|
|
1de50a9 |
|
|
|
1de50a9 |
float append(gr_segment * pSeg,
|
|
|
1de50a9 |
ImplLayoutArgs & rArgs,
|
|
|
1de50a9 |
const gr_slot * pSlot, float gOrigin,
|
|
|
1de50a9 |
float nextGlyphOrigin, float fScaling,
|
|
|
1de50a9 |
- long & rDXOffset, bool bIsBase, int baseChar);
|
|
|
1de50a9 |
+ long & rDXOffset, bool bIsBase, int baseChar, int baseGlyph, bool bRtl);
|
|
|
1de50a9 |
+ unsigned int ScanFwdForChar(int &findChar, bool fallback) const;
|
|
|
1de50a9 |
};
|
|
|
1de50a9 |
|
|
|
1de50a9 |
#endif // INCLUDED_VCL_INC_GRAPHITE_LAYOUT_HXX
|
|
|
1de50a9 |
diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx
|
|
|
1de50a9 |
index 6758df2..fe4abe7 100644
|
|
|
1de50a9 |
--- a/vcl/source/fontsubset/sft.cxx
|
|
|
1de50a9 |
+++ b/vcl/source/fontsubset/sft.cxx
|
|
|
1de50a9 |
@@ -1770,6 +1770,9 @@ int GetTTGlyphComponents(TrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal
|
|
|
1de50a9 |
|
|
|
1de50a9 |
const sal_uInt8* glyf = getTable(ttf, O_glyf);
|
|
|
1de50a9 |
const sal_uInt8* ptr = glyf + ttf->goffsets[glyphID];
|
|
|
1de50a9 |
+ const sal_uInt8* nptr = glyf + ttf->goffsets[glyphID+1];
|
|
|
1de50a9 |
+ if (nptr <= ptr)
|
|
|
1de50a9 |
+ return 0;
|
|
|
1de50a9 |
|
|
|
1de50a9 |
glyphlist.push_back( glyphID );
|
|
|
1de50a9 |
|
|
|
1de50a9 |
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
|
|
|
1de50a9 |
index f2974a2..44d1f45 100644
|
|
|
1de50a9 |
--- a/vcl/source/gdi/pdfwriter_impl.cxx
|
|
|
1de50a9 |
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
|
|
|
1de50a9 |
@@ -9006,22 +9006,27 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool
|
|
|
1de50a9 |
else if( pCharPosAry[i] >= nMinCharPos && pCharPosAry[i] <= nMaxCharPos )
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
int nChars = 1;
|
|
|
1de50a9 |
- aUnicodes.push_back( rText[ pCharPosAry[i] ] );
|
|
|
1de50a9 |
pUnicodesPerGlyph[i] = 1;
|
|
|
1de50a9 |
// try to handle ligatures and such
|
|
|
1de50a9 |
if( i < nGlyphs-1 )
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
nChars = pCharPosAry[i+1] - pCharPosAry[i];
|
|
|
1de50a9 |
+ int start = pCharPosAry[i];
|
|
|
1de50a9 |
// #i115618# fix for simple RTL+CTL cases
|
|
|
1de50a9 |
- // TODO: sanitize for RTL ligatures, more complex CTL, etc.
|
|
|
1de50a9 |
+ // supports RTL ligatures. TODO: more complex CTL, etc.
|
|
|
1de50a9 |
if( nChars < 0 )
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
nChars = -nChars;
|
|
|
1de50a9 |
- else if( nChars == 0 )
|
|
|
1de50a9 |
+ start = pCharPosAry[i+1] + 1;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+ else if (nChars == 0)
|
|
|
1de50a9 |
nChars = 1;
|
|
|
1de50a9 |
pUnicodesPerGlyph[i] = nChars;
|
|
|
1de50a9 |
- for( int n = 1; n < nChars; n++ )
|
|
|
1de50a9 |
- aUnicodes.push_back( rText[ pCharPosAry[i] + n ] );
|
|
|
1de50a9 |
+ for( int n = 0; n < nChars; n++ )
|
|
|
1de50a9 |
+ aUnicodes.push_back( rText[ start + n ] );
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
+ else
|
|
|
1de50a9 |
+ aUnicodes.push_back( rText[ pCharPosAry[i] ] );
|
|
|
1de50a9 |
// #i36691# hack that is needed because currently the pGlyphs[]
|
|
|
1de50a9 |
// argument is ignored for embeddable fonts and so the layout
|
|
|
1de50a9 |
// engine's glyph work is ignored (i.e. char mirroring)
|
|
|
1de50a9 |
diff --git a/vcl/source/glyphs/graphite_layout.cxx b/vcl/source/glyphs/graphite_layout.cxx
|
|
|
1de50a9 |
index a4aa99c..db50a22 100644
|
|
|
1de50a9 |
--- a/vcl/source/glyphs/graphite_layout.cxx
|
|
|
1de50a9 |
+++ b/vcl/source/glyphs/graphite_layout.cxx
|
|
|
1de50a9 |
@@ -27,7 +27,7 @@
|
|
|
1de50a9 |
#undef NDEBUG
|
|
|
1de50a9 |
#endif
|
|
|
1de50a9 |
|
|
|
1de50a9 |
-// #define GRLAYOUT_DEBUG 1
|
|
|
1de50a9 |
+//#define GRLAYOUT_DEBUG 1
|
|
|
1de50a9 |
|
|
|
1de50a9 |
#include <algorithm>
|
|
|
1de50a9 |
#include <cassert>
|
|
|
1de50a9 |
@@ -89,23 +89,6 @@ namespace
|
|
|
1de50a9 |
return !(b > i) && i < e;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
|
|
|
1de50a9 |
- int findSameDirLimit(const sal_Unicode* buffer, int charCount, bool rtl)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- UErrorCode status = U_ZERO_ERROR;
|
|
|
1de50a9 |
- UBiDi *ubidi = ubidi_openSized(charCount, 0, &status);
|
|
|
1de50a9 |
- int limit = 0;
|
|
|
1de50a9 |
- ubidi_setPara(ubidi, reinterpret_cast<const UChar *>(buffer), charCount,
|
|
|
1de50a9 |
- (rtl)?UBIDI_DEFAULT_RTL:UBIDI_DEFAULT_LTR, NULL, &status);
|
|
|
1de50a9 |
- UBiDiLevel level = 0;
|
|
|
1de50a9 |
- ubidi_getLogicalRun(ubidi, 0, &limit, &level);
|
|
|
1de50a9 |
- ubidi_close(ubidi);
|
|
|
1de50a9 |
- if ((rtl && !(level & 1)) || (!rtl && (level & 1)))
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- limit = 0;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- return limit;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
template <typename T>
|
|
|
1de50a9 |
T maximum(T a, T b)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
@@ -125,43 +108,21 @@ namespace
|
|
|
1de50a9 |
// o Querying clustering relationships.
|
|
|
1de50a9 |
// o manipulations that affect neighouring glyphs.
|
|
|
1de50a9 |
|
|
|
1de50a9 |
-const int GraphiteLayout::EXTRA_CONTEXT_LENGTH = 10;
|
|
|
1de50a9 |
+const int GraphiteLayout::EXTRA_CONTEXT_LENGTH = 32;
|
|
|
1de50a9 |
|
|
|
1de50a9 |
-// find first slot of cluster and first slot of subsequent cluster
|
|
|
1de50a9 |
-static void findFirstClusterSlot(const gr_slot* base, gr_slot const** first, gr_slot const** after, int * firstChar, int * lastChar, bool bRtl)
|
|
|
1de50a9 |
+const gr_slot *get_next_base(const gr_slot *slot, bool bRtl)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- if (gr_slot_attached_to(base) == NULL)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- *first = base;
|
|
|
1de50a9 |
- *after = (bRtl)? gr_slot_prev_in_segment(base) :
|
|
|
1de50a9 |
- gr_slot_next_in_segment(base);
|
|
|
1de50a9 |
- *firstChar = gr_slot_before(base);
|
|
|
1de50a9 |
- *lastChar = gr_slot_after(base);
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- const gr_slot * attachment = gr_slot_first_attachment(base);
|
|
|
1de50a9 |
- while (attachment)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- if (gr_slot_origin_X(*first) > gr_slot_origin_X(attachment))
|
|
|
1de50a9 |
- *first = attachment;
|
|
|
1de50a9 |
- const gr_slot* attachmentNext = (bRtl)?
|
|
|
1de50a9 |
- gr_slot_prev_in_segment(attachment) : gr_slot_next_in_segment(attachment);
|
|
|
1de50a9 |
- if (attachmentNext)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- if (*after && (gr_slot_origin_X(*after) < gr_slot_origin_X(attachmentNext)))
|
|
|
1de50a9 |
- *after = attachmentNext;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- *after = NULL;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- if (gr_slot_before(attachment) < *firstChar)
|
|
|
1de50a9 |
- *firstChar = gr_slot_before(attachment);
|
|
|
1de50a9 |
- if (gr_slot_after(attachment) > *lastChar)
|
|
|
1de50a9 |
- *lastChar = gr_slot_after(attachment);
|
|
|
1de50a9 |
- if (gr_slot_first_attachment(attachment))
|
|
|
1de50a9 |
- findFirstClusterSlot(attachment, first, after, firstChar, lastChar, bRtl);
|
|
|
1de50a9 |
- attachment = gr_slot_next_sibling_attachment(attachment);
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
+ for ( ; slot; slot = bRtl ? gr_slot_prev_in_segment(slot) : gr_slot_next_in_segment(slot))
|
|
|
1de50a9 |
+ if (!gr_slot_attached_to(slot) || gr_slot_can_insert_before(slot))
|
|
|
1de50a9 |
+ break;
|
|
|
1de50a9 |
+ return slot;
|
|
|
1de50a9 |
+}
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+bool isWhite(sal_Unicode nChar)
|
|
|
1de50a9 |
+{
|
|
|
1de50a9 |
+ if (nChar <= 0x0020 || nChar == 0x00A0 || (nChar >= 0x2000 && nChar <= 0x200F) || nChar == 0x3000)
|
|
|
1de50a9 |
+ return true;
|
|
|
1de50a9 |
+ return false;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
|
|
|
1de50a9 |
// The Graphite glyph stream is really a sequence of glyph attachment trees
|
|
|
1de50a9 |
@@ -169,202 +130,131 @@ static void findFirstClusterSlot(const gr_slot* base, gr_slot const** first, gr_
|
|
|
1de50a9 |
// finds each non-attached base glyph and calls append to record them as a
|
|
|
1de50a9 |
// sequence of clusters.
|
|
|
1de50a9 |
void
|
|
|
1de50a9 |
-GraphiteLayout::fillFrom(gr_segment * pSegment, ImplLayoutArgs &rArgs, float fScaling)
|
|
|
1de50a9 |
+GraphiteLayout::fillFrom(gr_segment * pSegment, ImplLayoutArgs &rArgs, float fScaling, bool bRtl, int lastCharPos)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- bool bRtl(rArgs.mnFlags & SalLayoutFlags::BiDiRtl);
|
|
|
1de50a9 |
- int nCharRequested = rArgs.mnEndCharPos - rArgs.mnMinCharPos;
|
|
|
1de50a9 |
- int nChar = gr_seg_n_cinfo(pSegment);
|
|
|
1de50a9 |
float fMinX = gr_seg_advance_X(pSegment);
|
|
|
1de50a9 |
float fMaxX = 0.0f;
|
|
|
1de50a9 |
long nDxOffset = 0; // from dropped glyphs
|
|
|
1de50a9 |
- int nFirstCharInCluster = 0;
|
|
|
1de50a9 |
- int nLastCharInCluster = 0;
|
|
|
1de50a9 |
+ int origNumGlyphs = mvGlyphs.size();
|
|
|
1de50a9 |
unsigned int nGlyphs = gr_seg_n_slots(pSegment);
|
|
|
1de50a9 |
- mvGlyph2Char.assign(nGlyphs, -1);
|
|
|
1de50a9 |
- mvGlyphs.reserve(nGlyphs);
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
- if (bRtl)
|
|
|
1de50a9 |
+ mvGlyph2Char.resize(mvGlyph2Char.size() + nGlyphs, -1);
|
|
|
1de50a9 |
+ mvGlyphs.reserve(mvGlyphs.size() + nGlyphs);
|
|
|
1de50a9 |
+ int clusterStart = -1;
|
|
|
1de50a9 |
+ int clusterFirstChar = -1;
|
|
|
1de50a9 |
+ const gr_slot *nextBaseSlot;
|
|
|
1de50a9 |
+ const sal_Unicode *pStr = rArgs.mpStr;
|
|
|
1de50a9 |
+ int firstChar;
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ if (!nGlyphs || lastCharPos - mnSegCharOffset == 0) return;
|
|
|
1de50a9 |
+ const gr_slot* baseSlot = bRtl ? gr_seg_last_slot(pSegment) : gr_seg_first_slot(pSegment);
|
|
|
1de50a9 |
+ // find first base
|
|
|
1de50a9 |
+ while (baseSlot && gr_slot_attached_to(baseSlot) != NULL && !gr_slot_can_insert_before(baseSlot))
|
|
|
1de50a9 |
+ baseSlot = bRtl ? gr_slot_prev_in_segment(baseSlot) : gr_slot_next_in_segment(baseSlot);
|
|
|
1de50a9 |
+ assert(baseSlot);
|
|
|
1de50a9 |
+ int nextChar = gr_cinfo_base(gr_seg_cinfo(pSegment, gr_slot_before(baseSlot))) + mnSegCharOffset;
|
|
|
1de50a9 |
+ float thisBoundary = 0.;
|
|
|
1de50a9 |
+ float nextBoundary = gr_slot_origin_X(baseSlot);
|
|
|
1de50a9 |
+ // now loop over bases
|
|
|
1de50a9 |
+ for ( ; baseSlot; baseSlot = nextBaseSlot)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- const gr_slot* baseSlot = gr_seg_last_slot(pSegment);
|
|
|
1de50a9 |
- // find first base
|
|
|
1de50a9 |
- while (baseSlot && (gr_slot_attached_to(baseSlot) != NULL))
|
|
|
1de50a9 |
- baseSlot = gr_slot_prev_in_segment(baseSlot);
|
|
|
1de50a9 |
- int iChar = nChar - 1;
|
|
|
1de50a9 |
- int iNextChar = nChar - 1;
|
|
|
1de50a9 |
- bool reordered = false;
|
|
|
1de50a9 |
- int nBaseGlyphIndex = 0;
|
|
|
1de50a9 |
- // now loop over bases
|
|
|
1de50a9 |
- while (baseSlot)
|
|
|
1de50a9 |
+ firstChar = nextChar;
|
|
|
1de50a9 |
+ thisBoundary = nextBoundary;
|
|
|
1de50a9 |
+ nextBaseSlot = get_next_base(bRtl ? gr_slot_prev_in_segment(baseSlot) : gr_slot_next_in_segment(baseSlot), bRtl);
|
|
|
1de50a9 |
+ nextChar = nextBaseSlot ? gr_cinfo_base(gr_seg_cinfo(pSegment, gr_slot_before(nextBaseSlot))) + mnSegCharOffset : -1;
|
|
|
1de50a9 |
+ nextBoundary = nextBaseSlot ? gr_slot_origin_X(nextBaseSlot) : gr_seg_advance_X(pSegment);
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ if (firstChar < mnMinCharPos || firstChar >= mnEndCharPos)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- bool bCluster = !reordered;
|
|
|
1de50a9 |
- const gr_slot * clusterFirst = NULL;
|
|
|
1de50a9 |
- const gr_slot * clusterAfter = NULL;
|
|
|
1de50a9 |
- int firstChar = -1;
|
|
|
1de50a9 |
- int lastChar = -1;
|
|
|
1de50a9 |
- findFirstClusterSlot(baseSlot, &clusterFirst, &clusterAfter, &firstChar, &lastChar, bRtl);
|
|
|
1de50a9 |
- iNextChar = minimum<int>(firstChar, iNextChar);
|
|
|
1de50a9 |
- if (bCluster)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- nBaseGlyphIndex = mvGlyphs.size();
|
|
|
1de50a9 |
- mvGlyph2Char[nBaseGlyphIndex] = iChar + mnSegCharOffset;
|
|
|
1de50a9 |
- nFirstCharInCluster = firstChar;
|
|
|
1de50a9 |
- nLastCharInCluster = lastChar;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- mvGlyph2Char[mvGlyphs.size()] = firstChar + mnSegCharOffset;
|
|
|
1de50a9 |
- nFirstCharInCluster = minimum<int>(firstChar, nFirstCharInCluster);
|
|
|
1de50a9 |
- nLastCharInCluster = maximum<int>(firstChar, nLastCharInCluster);
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- float leftBoundary = gr_slot_origin_X(clusterFirst);
|
|
|
1de50a9 |
- float rightBoundary = (clusterAfter)?
|
|
|
1de50a9 |
- gr_slot_origin_X(clusterAfter) : gr_seg_advance_X(pSegment);
|
|
|
1de50a9 |
- if (
|
|
|
1de50a9 |
- lastChar < iChar && clusterAfter &&
|
|
|
1de50a9 |
- (gr_cinfo_after(gr_seg_cinfo(pSegment, iChar)) >
|
|
|
1de50a9 |
- static_cast<int>(gr_slot_index(clusterAfter)))
|
|
|
1de50a9 |
- )
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- reordered = true;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- reordered = false;
|
|
|
1de50a9 |
- iChar = iNextChar - 1;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- if (mnSegCharOffset + nFirstCharInCluster >= mnMinCharPos &&
|
|
|
1de50a9 |
- mnSegCharOffset + nFirstCharInCluster < mnEndCharPos)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- fMinX = minimum<float>(fMinX, leftBoundary);
|
|
|
1de50a9 |
- fMaxX = maximum<float>(fMaxX, rightBoundary);
|
|
|
1de50a9 |
- if (!reordered)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- for (int i = nFirstCharInCluster; i <= nLastCharInCluster; i++)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- if (mnSegCharOffset + i >= mnEndCharPos)
|
|
|
1de50a9 |
- break;
|
|
|
1de50a9 |
- // from the point of view of the dx array, the xpos is
|
|
|
1de50a9 |
- // the origin of the first glyph of the cluster rtl
|
|
|
1de50a9 |
- mvCharDxs[mnSegCharOffset + i - mnMinCharPos] =
|
|
|
1de50a9 |
- static_cast<int>(leftBoundary * fScaling) + nDxOffset;
|
|
|
1de50a9 |
- mvCharBreaks[mnSegCharOffset + i - mnMinCharPos] = gr_cinfo_break_weight(gr_seg_cinfo(pSegment, i));
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- mvChar2BaseGlyph[mnSegCharOffset + nFirstCharInCluster - mnMinCharPos] = nBaseGlyphIndex;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- append(pSegment, rArgs, baseSlot, gr_slot_origin_X(baseSlot), rightBoundary, fScaling,
|
|
|
1de50a9 |
- nDxOffset, bCluster, mnSegCharOffset + firstChar);
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- if (mnSegCharOffset + nLastCharInCluster < mnMinCharPos)
|
|
|
1de50a9 |
- break;
|
|
|
1de50a9 |
- baseSlot = gr_slot_next_sibling_attachment(baseSlot);
|
|
|
1de50a9 |
+ // handle clipping of diacritic from base
|
|
|
1de50a9 |
+ nextBaseSlot = bRtl ? gr_slot_prev_in_segment(baseSlot) : gr_slot_next_in_segment(baseSlot);
|
|
|
1de50a9 |
+ nextBoundary = nextBaseSlot ? gr_slot_origin_X(nextBaseSlot) : gr_seg_advance_X(pSegment);
|
|
|
1de50a9 |
+ nextChar = nextBaseSlot ? gr_cinfo_base(gr_seg_cinfo(pSegment, gr_slot_before(nextBaseSlot))) + mnSegCharOffset : -1;
|
|
|
1de50a9 |
+ continue;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- const gr_slot* baseSlot = gr_seg_first_slot(pSegment);
|
|
|
1de50a9 |
- // find first base
|
|
|
1de50a9 |
- while (baseSlot && (gr_slot_attached_to(baseSlot) != NULL))
|
|
|
1de50a9 |
- baseSlot = gr_slot_next_in_segment(baseSlot);
|
|
|
1de50a9 |
- int iChar = 0; // relative to segment
|
|
|
1de50a9 |
- int iNextChar = 0;
|
|
|
1de50a9 |
- bool reordered = false;
|
|
|
1de50a9 |
- int nBaseGlyphIndex = 0;
|
|
|
1de50a9 |
- // now loop over bases
|
|
|
1de50a9 |
- while (baseSlot)
|
|
|
1de50a9 |
+ // handle reordered clusters. Presumes reordered glyphs have monotonic opposite char index until the cluster base.
|
|
|
1de50a9 |
+ bool isReordered = (nextBaseSlot && ((bRtl != (gr_cinfo_base(gr_seg_cinfo(pSegment, gr_slot_before(nextBaseSlot))) < firstChar - mnSegCharOffset))
|
|
|
1de50a9 |
+ || gr_cinfo_base(gr_seg_cinfo(pSegment, gr_slot_before(nextBaseSlot))) == firstChar - mnSegCharOffset));
|
|
|
1de50a9 |
+ if (clusterStart >= 0 && !isReordered) // we hit the base (end) of a reordered cluster
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- bool bCluster = !reordered;
|
|
|
1de50a9 |
- const gr_slot * clusterFirst = NULL;
|
|
|
1de50a9 |
- const gr_slot * clusterAfter = NULL;
|
|
|
1de50a9 |
- int firstChar = -1;
|
|
|
1de50a9 |
- int lastChar = -1;
|
|
|
1de50a9 |
- findFirstClusterSlot(baseSlot, &clusterFirst, &clusterAfter, &firstChar, &lastChar, bRtl);
|
|
|
1de50a9 |
- iNextChar = maximum<int>(lastChar, iNextChar);
|
|
|
1de50a9 |
- if (bCluster)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- nBaseGlyphIndex = mvGlyphs.size();
|
|
|
1de50a9 |
- mvGlyph2Char[nBaseGlyphIndex] = iChar + mnSegCharOffset;
|
|
|
1de50a9 |
- nFirstCharInCluster = firstChar;
|
|
|
1de50a9 |
- nLastCharInCluster = lastChar;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- mvGlyph2Char[mvGlyphs.size()] = firstChar + mnSegCharOffset;
|
|
|
1de50a9 |
- nFirstCharInCluster = minimum<int>(firstChar, nFirstCharInCluster);
|
|
|
1de50a9 |
- nLastCharInCluster = maximum<int>(lastChar, nLastCharInCluster);
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- if (
|
|
|
1de50a9 |
- firstChar > iChar &&
|
|
|
1de50a9 |
- (gr_cinfo_before(gr_seg_cinfo(pSegment, iChar)) >
|
|
|
1de50a9 |
- static_cast<int>(gr_slot_index(clusterFirst)))
|
|
|
1de50a9 |
- )
|
|
|
1de50a9 |
+ int clusterEnd = mvGlyphs.size();
|
|
|
1de50a9 |
+ for (int i = clusterStart; i < clusterEnd; ++i)
|
|
|
1de50a9 |
+ mvGlyph2Char[i] = firstChar;
|
|
|
1de50a9 |
+ if (bRtl)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- reordered = true;
|
|
|
1de50a9 |
+ for ( ; clusterFirstChar < firstChar; ++clusterFirstChar)
|
|
|
1de50a9 |
+ if (clusterFirstChar >= mnMinCharPos && clusterFirstChar < mnEndCharPos)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ mvChar2BaseGlyph[clusterFirstChar - mnMinCharPos] = clusterStart; // lowest glyphItem index
|
|
|
1de50a9 |
+ mvCharDxs[clusterFirstChar - mnMinCharPos] = static_cast<int>(thisBoundary * fScaling) + mnWidth + nDxOffset;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
else
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- reordered = false;
|
|
|
1de50a9 |
- iChar = iNextChar + 1;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- float leftBoundary = gr_slot_origin_X(clusterFirst);
|
|
|
1de50a9 |
- float rightBoundary = (clusterAfter)?
|
|
|
1de50a9 |
- gr_slot_origin_X(clusterAfter) : gr_seg_advance_X(pSegment);
|
|
|
1de50a9 |
- int bFirstChar = gr_cinfo_base(gr_seg_cinfo(pSegment, nFirstCharInCluster));
|
|
|
1de50a9 |
- if (mnSegCharOffset + bFirstChar >= mnMinCharPos &&
|
|
|
1de50a9 |
- mnSegCharOffset + bFirstChar < mnEndCharPos)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- fMinX = minimum<float>(fMinX, leftBoundary);
|
|
|
1de50a9 |
- fMaxX = maximum<float>(fMaxX, rightBoundary);
|
|
|
1de50a9 |
- if (!reordered)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- for (int i = nFirstCharInCluster; i <= nLastCharInCluster; i++)
|
|
|
1de50a9 |
+ for ( ; clusterFirstChar > firstChar; --clusterFirstChar)
|
|
|
1de50a9 |
+ if (clusterFirstChar < mnEndCharPos && clusterFirstChar >= mnMinCharPos)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- int ibase = gr_cinfo_base(gr_seg_cinfo(pSegment, i));
|
|
|
1de50a9 |
- if (mnSegCharOffset + ibase >= mnEndCharPos)
|
|
|
1de50a9 |
- break;
|
|
|
1de50a9 |
- // from the point of view of the dx array, the xpos is
|
|
|
1de50a9 |
- // the origin of the first glyph of the next cluster ltr
|
|
|
1de50a9 |
- mvCharDxs[mnSegCharOffset + ibase - mnMinCharPos] =
|
|
|
1de50a9 |
- static_cast<int>(rightBoundary * fScaling) + nDxOffset;
|
|
|
1de50a9 |
- mvCharBreaks[mnSegCharOffset + ibase - mnMinCharPos] = gr_cinfo_break_weight(gr_seg_cinfo(pSegment, i));
|
|
|
1de50a9 |
+ mvChar2BaseGlyph[clusterFirstChar - mnMinCharPos] = clusterStart;
|
|
|
1de50a9 |
+ mvCharDxs[clusterFirstChar - mnMinCharPos] = static_cast<int>(nextBoundary * fScaling) + mnWidth + nDxOffset;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
- // only set mvChar2BaseGlyph for first character of cluster
|
|
|
1de50a9 |
- mvChar2BaseGlyph[mnSegCharOffset + bFirstChar - mnMinCharPos] = nBaseGlyphIndex;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- append(pSegment, rArgs, baseSlot, gr_slot_origin_X(baseSlot), rightBoundary, fScaling,
|
|
|
1de50a9 |
- nDxOffset, true, mnSegCharOffset + firstChar);
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
- if (mnSegCharOffset + bFirstChar >= mnEndCharPos)
|
|
|
1de50a9 |
- break;
|
|
|
1de50a9 |
- baseSlot = gr_slot_next_sibling_attachment(baseSlot);
|
|
|
1de50a9 |
+ clusterStart = -1;
|
|
|
1de50a9 |
+ clusterFirstChar = -1;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+ else if (clusterStart < 0 && isReordered) // we hit the start of a reordered cluster
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ clusterStart = mvGlyphs.size();
|
|
|
1de50a9 |
+ clusterFirstChar = firstChar;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ int baseGlyph = mvGlyphs.size();
|
|
|
1de50a9 |
+ int scaledGlyphPos = round_to_long(gr_slot_origin_X(baseSlot) * fScaling) + mnWidth + nDxOffset;
|
|
|
1de50a9 |
+ if (mvChar2Glyph[firstChar - mnMinCharPos] == -1 || mvGlyphs[mvChar2Glyph[firstChar - mnMinCharPos]].maLinearPos.X() < scaledGlyphPos)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ mvChar2Glyph[firstChar - mnMinCharPos] = mvGlyphs.size();
|
|
|
1de50a9 |
+ mvCharDxs[firstChar - mnMinCharPos] = static_cast<int>((bRtl ? thisBoundary : nextBoundary) * fScaling) + mnWidth + nDxOffset;
|
|
|
1de50a9 |
+ mvChar2BaseGlyph[firstChar - mnMinCharPos] = baseGlyph;
|
|
|
1de50a9 |
+ mvCharBreaks[firstChar - mnMinCharPos] = gr_cinfo_break_weight(gr_seg_cinfo(pSegment, gr_slot_before(baseSlot)));
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
+ mvGlyph2Char[baseGlyph] = firstChar;
|
|
|
1de50a9 |
+ append(pSegment, rArgs, baseSlot, thisBoundary, nextBoundary, fScaling, nDxOffset, true, firstChar, baseGlyph, bRtl);
|
|
|
1de50a9 |
+ if (thisBoundary < fMinX) fMinX = thisBoundary;
|
|
|
1de50a9 |
+ if (nextBoundary > fMaxX && (nextChar < mnMinCharPos || nextChar >= mnEndCharPos || !isWhite(pStr[nextChar]) || fMaxX <= 0.0f))
|
|
|
1de50a9 |
+ fMaxX = nextBoundary;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
long nXOffset = round_to_long(fMinX * fScaling);
|
|
|
1de50a9 |
- mnWidth = round_to_long(fMaxX * fScaling) - nXOffset + nDxOffset;
|
|
|
1de50a9 |
- if (mnWidth < 0)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- // This can happen when there was no base inside the range
|
|
|
1de50a9 |
- mnWidth = 0;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
+ long nXEnd = round_to_long(fMaxX * fScaling);
|
|
|
1de50a9 |
+ int nCharRequested = minimum<int>(lastCharPos, mnEndCharPos) - mnMinCharPos;
|
|
|
1de50a9 |
+ int firstCharOffset = maximum<int>(mnSegCharOffset, mnMinCharPos) - mnMinCharPos;
|
|
|
1de50a9 |
// fill up non-base char dx with cluster widths from previous base glyph
|
|
|
1de50a9 |
if (bRtl)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
if (mvCharDxs[nCharRequested-1] == -1)
|
|
|
1de50a9 |
- mvCharDxs[nCharRequested-1] = 0;
|
|
|
1de50a9 |
+ mvCharDxs[nCharRequested-1] = nXEnd - nXOffset + mnWidth + nDxOffset;
|
|
|
1de50a9 |
else
|
|
|
1de50a9 |
- mvCharDxs[nCharRequested-1] -= nXOffset;
|
|
|
1de50a9 |
- for (int i = nCharRequested - 2; i >= 0; i--)
|
|
|
1de50a9 |
+ mvCharDxs[nCharRequested-1] = nXEnd - mvCharDxs[nCharRequested-1] + 2 * (mnWidth + nDxOffset);
|
|
|
1de50a9 |
+#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
+ fprintf(grLog(),"%d,%d ", nCharRequested - 1, (int)mvCharDxs[nCharRequested-1]);
|
|
|
1de50a9 |
+#endif
|
|
|
1de50a9 |
+ for (int i = nCharRequested - 2; i >= firstCharOffset; i--)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
if (mvCharDxs[i] == -1) mvCharDxs[i] = mvCharDxs[i+1];
|
|
|
1de50a9 |
- else mvCharDxs[i] -= nXOffset;
|
|
|
1de50a9 |
+ else mvCharDxs[i] = nXEnd - mvCharDxs[i] + 2 * (mnWidth + nDxOffset);
|
|
|
1de50a9 |
+#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
+ fprintf(grLog(),"%d,%d ", (int)i, (int)mvCharDxs[i]);
|
|
|
1de50a9 |
+#endif
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
else
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- if (mvCharDxs[0] == -1)
|
|
|
1de50a9 |
- mvCharDxs[0] = 0;
|
|
|
1de50a9 |
+ if (mvCharDxs[firstCharOffset] == -1)
|
|
|
1de50a9 |
+ mvCharDxs[firstCharOffset] = 0;
|
|
|
1de50a9 |
else
|
|
|
1de50a9 |
- mvCharDxs[0] -= nXOffset;
|
|
|
1de50a9 |
- for (int i = 1; i < nCharRequested; i++)
|
|
|
1de50a9 |
+ mvCharDxs[firstCharOffset] -= nXOffset;
|
|
|
1de50a9 |
+#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
+ fprintf(grLog(),"%d,%d ", firstCharOffset, (int)mvCharDxs[firstCharOffset]);
|
|
|
1de50a9 |
+#endif
|
|
|
1de50a9 |
+ for (int i = firstCharOffset + 1; i < nCharRequested; i++)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
if (mvCharDxs[i] == -1) mvCharDxs[i] = mvCharDxs[i-1];
|
|
|
1de50a9 |
else mvCharDxs[i] -= nXOffset;
|
|
|
1de50a9 |
@@ -376,11 +266,17 @@ GraphiteLayout::fillFrom(gr_segment * pSegment, ImplLayoutArgs &rArgs, float fSc
|
|
|
1de50a9 |
// remove offset due to context if there is one
|
|
|
1de50a9 |
if (nXOffset != 0)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- for (size_t i = 0; i < mvGlyphs.size(); i++)
|
|
|
1de50a9 |
+ for (size_t i = origNumGlyphs; i < mvGlyphs.size(); i++)
|
|
|
1de50a9 |
mvGlyphs[i].maLinearPos.X() -= nXOffset;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
+ mnWidth += nXEnd - nXOffset + nDxOffset;
|
|
|
1de50a9 |
+ if (mnWidth < 0)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ // This can happen when there was no base inside the range
|
|
|
1de50a9 |
+ mnWidth = 0;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
- fprintf(grLog(), "fillFrom %" SAL_PRI_SIZET "u glyphs offset %ld width %ld\n", mvGlyphs.size(), nXOffset, mnWidth);
|
|
|
1de50a9 |
+ fprintf(grLog(), "fillFrom %" SAL_PRI_SIZET "u glyphs offset %ld width %ld for %d\n", mvGlyphs.size(), nXOffset, mnWidth, nCharRequested);
|
|
|
1de50a9 |
#endif
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
|
|
|
1de50a9 |
@@ -389,37 +285,29 @@ GraphiteLayout::fillFrom(gr_segment * pSegment, ImplLayoutArgs &rArgs, float fSc
|
|
|
1de50a9 |
float
|
|
|
1de50a9 |
GraphiteLayout::append(gr_segment *pSeg, ImplLayoutArgs &rArgs,
|
|
|
1de50a9 |
const gr_slot * gi, float gOrigin, float nextGlyphOrigin, float scaling, long & rDXOffset,
|
|
|
1de50a9 |
- bool bIsBase, int baseChar)
|
|
|
1de50a9 |
+ bool bIsBase, int baseChar, int baseGlyph, bool bRtl)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- bool bRtl(rArgs.mnFlags & SalLayoutFlags::BiDiRtl);
|
|
|
1de50a9 |
- float nextOrigin;
|
|
|
1de50a9 |
assert(gi);
|
|
|
1de50a9 |
- assert(gr_slot_before(gi) <= gr_slot_after(gi));
|
|
|
1de50a9 |
- int firstChar = gr_slot_before(gi) + mnSegCharOffset;
|
|
|
1de50a9 |
+ // assert(gr_slot_before(gi) <= gr_slot_after(gi));
|
|
|
1de50a9 |
+ int firstChar = gr_cinfo_base(gr_seg_cinfo(pSeg, gr_slot_before(gi))) + mnSegCharOffset;
|
|
|
1de50a9 |
assert(mvGlyphs.size() < mvGlyph2Char.size());
|
|
|
1de50a9 |
- if (!bIsBase) mvGlyph2Char[mvGlyphs.size()] = baseChar;//firstChar;
|
|
|
1de50a9 |
- // is the next glyph attached or in the next cluster?
|
|
|
1de50a9 |
- //glyph_set_range_t iAttached = gi.attachedClusterGlyphs();
|
|
|
1de50a9 |
- const gr_slot * pFirstAttached = gr_slot_first_attachment(gi);
|
|
|
1de50a9 |
- const gr_slot * pNextSibling = gr_slot_next_sibling_attachment(gi);
|
|
|
1de50a9 |
- if (pFirstAttached)
|
|
|
1de50a9 |
- nextOrigin = gr_slot_origin_X(pFirstAttached);
|
|
|
1de50a9 |
- else if (!bIsBase && pNextSibling)
|
|
|
1de50a9 |
- nextOrigin = gr_slot_origin_X(pNextSibling);
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- nextOrigin = nextGlyphOrigin;
|
|
|
1de50a9 |
+ if (firstChar < mnMinCharPos || firstChar >= mnEndCharPos)
|
|
|
1de50a9 |
+ return nextGlyphOrigin;
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
long glyphId = gr_slot_gid(gi);
|
|
|
1de50a9 |
long deltaOffset = 0;
|
|
|
1de50a9 |
- int scaledGlyphPos = round_to_long(gr_slot_origin_X(gi) * scaling);
|
|
|
1de50a9 |
- int glyphWidth = round_to_long((nextOrigin - gOrigin) * scaling);
|
|
|
1de50a9 |
-// if (glyphWidth < 0)
|
|
|
1de50a9 |
-// {
|
|
|
1de50a9 |
-// nextOrigin = gOrigin;
|
|
|
1de50a9 |
-// glyphWidth = 0;
|
|
|
1de50a9 |
-// }
|
|
|
1de50a9 |
+ int scaledGlyphPos = round_to_long(gr_slot_origin_X(gi) * scaling) + mnWidth + rDXOffset;
|
|
|
1de50a9 |
+ int glyphWidth = round_to_long((nextGlyphOrigin - gOrigin) * scaling);
|
|
|
1de50a9 |
+ if (!bIsBase)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ mvChar2BaseGlyph[firstChar - mnMinCharPos] = baseGlyph;
|
|
|
1de50a9 |
+ mvCharDxs[firstChar - mnMinCharPos] = mvCharDxs[baseChar - mnMinCharPos];
|
|
|
1de50a9 |
+ mvCharBreaks[firstChar - mnMinCharPos] = gr_cinfo_break_weight(gr_seg_cinfo(pSeg, gr_slot_before(gi)));
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
- fprintf(grLog(),"c%d g%ld,X%d W%d nX%f ", firstChar, glyphId,
|
|
|
1de50a9 |
- (int)(gr_slot_origin_X(gi) * scaling), glyphWidth, nextOrigin * scaling);
|
|
|
1de50a9 |
+ fprintf(grLog(),"c%d g%ld,X%d W%d nX%f @%d=%d ", firstChar, glyphId,
|
|
|
1de50a9 |
+ scaledGlyphPos, glyphWidth, nextGlyphOrigin * scaling, mvChar2Glyph[firstChar-mnMinCharPos], mvCharDxs[firstChar-mnMinCharPos]);
|
|
|
1de50a9 |
#endif
|
|
|
1de50a9 |
if (glyphId == 0)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
@@ -449,11 +337,12 @@ GraphiteLayout::append(gr_segment *pSeg, ImplLayoutArgs &rArgs,
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
// append this glyph. Set the cluster flag if this glyph is attached to another
|
|
|
1de50a9 |
long nGlyphFlags = bIsBase ? 0 : GlyphItem::IS_IN_CLUSTER;
|
|
|
1de50a9 |
+ if (gr_slot_attached_to(gi))
|
|
|
1de50a9 |
+ nGlyphFlags |= GlyphItem::IS_DIACRITIC;
|
|
|
1de50a9 |
nGlyphFlags |= (bRtl)? GlyphItem::IS_RTL_GLYPH : 0;
|
|
|
1de50a9 |
GlyphItem aGlyphItem(mvGlyphs.size(),
|
|
|
1de50a9 |
glyphId,
|
|
|
1de50a9 |
- Point(scaledGlyphPos + rDXOffset,
|
|
|
1de50a9 |
- round_to_long((-gr_slot_origin_Y(gi) * scaling))),
|
|
|
1de50a9 |
+ Point(scaledGlyphPos, round_to_long((-gr_slot_origin_Y(gi) * scaling))),
|
|
|
1de50a9 |
nGlyphFlags,
|
|
|
1de50a9 |
glyphWidth);
|
|
|
1de50a9 |
if (glyphId != static_cast<long>(GF_DROPPED))
|
|
|
1de50a9 |
@@ -464,9 +353,10 @@ GraphiteLayout::append(gr_segment *pSeg, ImplLayoutArgs &rArgs,
|
|
|
1de50a9 |
rDXOffset += deltaOffset;
|
|
|
1de50a9 |
|
|
|
1de50a9 |
// Recursively append all the attached glyphs.
|
|
|
1de50a9 |
- float cOrigin = nextOrigin;
|
|
|
1de50a9 |
+ float cOrigin = nextGlyphOrigin;
|
|
|
1de50a9 |
for (const gr_slot * agi = gr_slot_first_attachment(gi); agi != NULL; agi = gr_slot_next_sibling_attachment(agi))
|
|
|
1de50a9 |
- cOrigin = append(pSeg, rArgs, agi, cOrigin, nextGlyphOrigin, scaling, rDXOffset, false, baseChar);
|
|
|
1de50a9 |
+ if (!gr_slot_can_insert_before(agi))
|
|
|
1de50a9 |
+ cOrigin = append(pSeg, rArgs, agi, cOrigin, nextGlyphOrigin, scaling, rDXOffset, false, baseChar, baseGlyph, bRtl);
|
|
|
1de50a9 |
|
|
|
1de50a9 |
return cOrigin;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
@@ -500,6 +390,7 @@ void GraphiteLayout::clear()
|
|
|
1de50a9 |
mvGlyphs.clear();
|
|
|
1de50a9 |
mvCharDxs.clear();
|
|
|
1de50a9 |
mvChar2BaseGlyph.clear();
|
|
|
1de50a9 |
+ mvChar2Glyph.clear();
|
|
|
1de50a9 |
mvGlyph2Char.clear();
|
|
|
1de50a9 |
|
|
|
1de50a9 |
// Reset the state to the empty state.
|
|
|
1de50a9 |
@@ -510,170 +401,61 @@ void GraphiteLayout::clear()
|
|
|
1de50a9 |
// This method shouldn't be called on windows, since it needs the dc reset
|
|
|
1de50a9 |
bool GraphiteLayout::LayoutText(ImplLayoutArgs & rArgs)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
+ clear();
|
|
|
1de50a9 |
bool success = true;
|
|
|
1de50a9 |
- if (rArgs.mnMinCharPos < rArgs.mnEndCharPos)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- gr_segment * pSegment = CreateSegment(rArgs);
|
|
|
1de50a9 |
- if (!pSegment)
|
|
|
1de50a9 |
- return false;
|
|
|
1de50a9 |
- success = LayoutGlyphs(rArgs, pSegment);
|
|
|
1de50a9 |
- if (pSegment)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- gr_seg_destroy(pSegment);
|
|
|
1de50a9 |
- pSegment = NULL;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- clear();
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- return success;
|
|
|
1de50a9 |
-}
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
-gr_segment * GraphiteLayout::CreateSegment(ImplLayoutArgs& rArgs)
|
|
|
1de50a9 |
-{
|
|
|
1de50a9 |
- assert(rArgs.mnLength >= 0);
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
- gr_segment * pSegment = NULL;
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
+ if (rArgs.mnMinCharPos >= rArgs.mnEndCharPos)
|
|
|
1de50a9 |
+ return success;
|
|
|
1de50a9 |
// Set the SalLayouts values to be the initial ones.
|
|
|
1de50a9 |
SalLayout::AdjustLayout(rArgs);
|
|
|
1de50a9 |
// TODO check if this is needed
|
|
|
1de50a9 |
if (mnUnitsPerPixel > 1)
|
|
|
1de50a9 |
mfScaling = 1.0f / mnUnitsPerPixel;
|
|
|
1de50a9 |
+ mvCharDxs.assign(mnEndCharPos - mnMinCharPos, -1);
|
|
|
1de50a9 |
+ mvChar2BaseGlyph.assign(mnEndCharPos - mnMinCharPos, -1);
|
|
|
1de50a9 |
+ mvChar2Glyph.assign(mnEndCharPos - mnMinCharPos, -1);
|
|
|
1de50a9 |
+ mvCharBreaks.assign(mnEndCharPos - mnMinCharPos, 0);
|
|
|
1de50a9 |
|
|
|
1de50a9 |
- // Clear out any previous buffers
|
|
|
1de50a9 |
- clear();
|
|
|
1de50a9 |
- bool bRtl(mnLayoutFlags & SalLayoutFlags::BiDiRtl);
|
|
|
1de50a9 |
- try
|
|
|
1de50a9 |
+#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
+ fprintf(grLog(), "New Graphite LayoutText\n");
|
|
|
1de50a9 |
+#endif
|
|
|
1de50a9 |
+ success = false;
|
|
|
1de50a9 |
+ while (true)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- // Don't set RTL if font doesn't support it otherwise it forces rtl on
|
|
|
1de50a9 |
- // everything
|
|
|
1de50a9 |
- //if (bRtl && (mrFont.getSupportedScriptDirections() & gr::kfsdcHorizRtl))
|
|
|
1de50a9 |
- // maLayout.setRightToLeft(bRtl);
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
- // Context is often needed beyond the specified end, however, we don't
|
|
|
1de50a9 |
- // want it if there has been a direction change, since it is hard
|
|
|
1de50a9 |
- // to tell between reordering within one direction and multi-directional
|
|
|
1de50a9 |
- // text. Extra context, can also cause problems with ligatures stradling
|
|
|
1de50a9 |
- // a hyphenation point, so disable if CTL is disabled.
|
|
|
1de50a9 |
- mnSegCharOffset = rArgs.mnMinCharPos;
|
|
|
1de50a9 |
- int limit = rArgs.mnEndCharPos;
|
|
|
1de50a9 |
- if (!(SalLayoutFlags::ComplexDisabled & rArgs.mnFlags))
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- const int nSegCharMin = maximum<int>(0, mnMinCharPos - EXTRA_CONTEXT_LENGTH);
|
|
|
1de50a9 |
- const int nSegCharLimit = minimum(rArgs.mnLength, mnEndCharPos + EXTRA_CONTEXT_LENGTH);
|
|
|
1de50a9 |
- if (nSegCharMin < mnSegCharOffset)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- int sameDirEnd = findSameDirLimit(rArgs.mpStr + nSegCharMin,
|
|
|
1de50a9 |
- rArgs.mnEndCharPos - nSegCharMin, bRtl);
|
|
|
1de50a9 |
- if (sameDirEnd == rArgs.mnEndCharPos)
|
|
|
1de50a9 |
- mnSegCharOffset = nSegCharMin;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- if (nSegCharLimit > limit)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- limit += findSameDirLimit(rArgs.mpStr + rArgs.mnEndCharPos,
|
|
|
1de50a9 |
- nSegCharLimit - rArgs.mnEndCharPos, bRtl);
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
+ int nBidiMinRunPos, nBidiEndRunPos;
|
|
|
1de50a9 |
+ bool bRightToLeft;
|
|
|
1de50a9 |
+ if (!rArgs.GetNextRun(&nBidiMinRunPos, &nBidiEndRunPos, &bRightToLeft))
|
|
|
1de50a9 |
+ break;
|
|
|
1de50a9 |
|
|
|
1de50a9 |
- size_t numchars = gr_count_unicode_characters(gr_utf16, rArgs.mpStr + mnSegCharOffset,
|
|
|
1de50a9 |
- rArgs.mpStr + (rArgs.mnLength > limit + 64 ? limit + 64 : rArgs.mnLength), NULL);
|
|
|
1de50a9 |
- static com::sun::star::uno::Reference< com::sun::star::i18n::XCharacterClassification > xCharClass;
|
|
|
1de50a9 |
- if ( !xCharClass.is() )
|
|
|
1de50a9 |
- xCharClass = vcl::unohelper::CreateCharacterClassification();
|
|
|
1de50a9 |
- size_t numchars2 = rArgs.mnEndCharPos - mnSegCharOffset; // fdo#52540, fdo#68313, fdo#70666 avoid bad ligature replacement, fdo#88051 layout problem
|
|
|
1de50a9 |
- if (numchars > numchars2 && (rArgs.mpStr[mnSegCharOffset + numchars2] == '\t' ||
|
|
|
1de50a9 |
- xCharClass->getType(rArgs.mpStr + mnSegCharOffset, numchars2 + 1) == ::com::sun::star::i18n::UnicodeType::LOWERCASE_LETTER))
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- numchars = numchars2;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- if (mpFeatures)
|
|
|
1de50a9 |
- pSegment = gr_make_seg(mpFont, mpFace, 0, mpFeatures->values(), gr_utf16,
|
|
|
1de50a9 |
- rArgs.mpStr + mnSegCharOffset, numchars, bRtl);
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- pSegment = gr_make_seg(mpFont, mpFace, 0, NULL, gr_utf16,
|
|
|
1de50a9 |
- rArgs.mpStr + mnSegCharOffset, numchars, bRtl);
|
|
|
1de50a9 |
+ if (nBidiEndRunPos < mnMinCharPos || nBidiMinRunPos >= mnEndCharPos)
|
|
|
1de50a9 |
+ continue;
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ if (nBidiMinRunPos == mnMinCharPos)
|
|
|
1de50a9 |
+ nBidiMinRunPos = maximum<int>(0, nBidiMinRunPos - EXTRA_CONTEXT_LENGTH);
|
|
|
1de50a9 |
+ if (nBidiEndRunPos == mnEndCharPos)
|
|
|
1de50a9 |
+ nBidiEndRunPos = minimum<int>(rArgs.mnLength, nBidiEndRunPos + EXTRA_CONTEXT_LENGTH);
|
|
|
1de50a9 |
+ size_t numchars = gr_count_unicode_characters(gr_utf16, rArgs.mpStr + nBidiMinRunPos,
|
|
|
1de50a9 |
+ rArgs.mpStr + nBidiEndRunPos, NULL);
|
|
|
1de50a9 |
+ gr_segment * pSegment = gr_make_seg(mpFont, mpFace, 0, mpFeatures ? mpFeatures->values() : NULL,
|
|
|
1de50a9 |
+ gr_utf16, rArgs.mpStr + nBidiMinRunPos, numchars, 2 | int(bRightToLeft));
|
|
|
1de50a9 |
|
|
|
1de50a9 |
- //pSegment = new gr::RangeSegment((gr::Font *)&mrFont, mpTextSrc, &maLayout, mnMinCharPos, limit);
|
|
|
1de50a9 |
if (pSegment != NULL)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
+ success = true;
|
|
|
1de50a9 |
+ mnSegCharOffset = nBidiMinRunPos;
|
|
|
1de50a9 |
#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
- fprintf(grLog(),"Gr::LayoutText %d-%d, context %d, len %d, numchars %" SAL_PRI_SIZET "u, rtl %d scaling %f:", rArgs.mnMinCharPos,
|
|
|
1de50a9 |
- rArgs.mnEndCharPos, limit, rArgs.mnLength, numchars, bRtl, mfScaling);
|
|
|
1de50a9 |
- for (int i = mnSegCharOffset; i < limit; ++i)
|
|
|
1de50a9 |
+ fprintf(grLog(),"Gr::LayoutText %d-%d, context %d-%d, len %d, numchars %" SAL_PRI_SIZET "u, rtl %d scaling %f:",
|
|
|
1de50a9 |
+ rArgs.mnMinCharPos, rArgs.mnEndCharPos,
|
|
|
1de50a9 |
+ nBidiMinRunPos, nBidiEndRunPos,
|
|
|
1de50a9 |
+ rArgs.mnLength, numchars, bRightToLeft, mfScaling);
|
|
|
1de50a9 |
+ for (int i = mnSegCharOffset; i < nBidiEndRunPos; ++i)
|
|
|
1de50a9 |
fprintf(grLog(), " %04X", rArgs.mpStr[i]);
|
|
|
1de50a9 |
fprintf(grLog(), "\n");
|
|
|
1de50a9 |
#endif
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
-#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
- fprintf(grLog(), "Gr::LayoutText failed: ");
|
|
|
1de50a9 |
- for (int i = mnMinCharPos; i < limit; i++)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- fprintf(grLog(), "%04x ", rArgs.mpStr[i]);
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- fprintf(grLog(), "\n");
|
|
|
1de50a9 |
-#endif
|
|
|
1de50a9 |
- clear();
|
|
|
1de50a9 |
- return NULL;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- catch (...)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- clear(); // destroy the text source and any partially built segments.
|
|
|
1de50a9 |
- return NULL;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- return pSegment;
|
|
|
1de50a9 |
-}
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
-bool GraphiteLayout::LayoutGlyphs(ImplLayoutArgs& rArgs, gr_segment * pSegment)
|
|
|
1de50a9 |
-{
|
|
|
1de50a9 |
- // Calculate the initial character dxs.
|
|
|
1de50a9 |
- mvCharDxs.assign(mnEndCharPos - mnMinCharPos, -1);
|
|
|
1de50a9 |
- mvChar2BaseGlyph.assign(mnEndCharPos - mnMinCharPos, -1);
|
|
|
1de50a9 |
- mvCharBreaks.assign(mnEndCharPos - mnMinCharPos, 0);
|
|
|
1de50a9 |
- mnWidth = 0;
|
|
|
1de50a9 |
- if (mvCharDxs.size() > 0)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- // Discover all the clusters.
|
|
|
1de50a9 |
- try
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- bool bRtl(mnLayoutFlags & SalLayoutFlags::BiDiRtl);
|
|
|
1de50a9 |
- fillFrom(pSegment, rArgs, mfScaling);
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
- if (bRtl)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- // not needed for adjacent differences, but for mouse clicks to char
|
|
|
1de50a9 |
- std::transform(mvCharDxs.begin(), mvCharDxs.end(), mvCharDxs.begin(),
|
|
|
1de50a9 |
- std::bind1st(std::minus<long>(), mnWidth));
|
|
|
1de50a9 |
- // fixup last dx to ensure it always equals the width
|
|
|
1de50a9 |
- mvCharDxs[mvCharDxs.size() - 1] = mnWidth;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- catch (const std::exception &e)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
-#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
- fprintf(grLog(),"LayoutGlyphs failed %s\n", e.what());
|
|
|
1de50a9 |
-#else
|
|
|
1de50a9 |
- (void)e;
|
|
|
1de50a9 |
-#endif
|
|
|
1de50a9 |
- return false;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- catch (...)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
-#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
- fprintf(grLog(),"LayoutGlyphs failed with exception");
|
|
|
1de50a9 |
-#endif
|
|
|
1de50a9 |
- return false;
|
|
|
1de50a9 |
+ fillFrom(pSegment, rArgs, mfScaling, bRightToLeft, nBidiEndRunPos);
|
|
|
1de50a9 |
+ gr_seg_destroy(pSegment);
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- mnWidth = 0;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- return true;
|
|
|
1de50a9 |
+ return success;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
|
|
|
1de50a9 |
sal_Int32 GraphiteLayout::GetTextBreak(DeviceCoordinate maxmnWidth, DeviceCoordinate char_extra, int factor) const
|
|
|
1de50a9 |
@@ -695,12 +477,12 @@ sal_Int32 GraphiteLayout::GetTextBreak(DeviceCoordinate maxmnWidth, DeviceCoordi
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
nWidth += char_extra;
|
|
|
1de50a9 |
if (nWidth > maxmnWidth) break;
|
|
|
1de50a9 |
- if (mvChar2BaseGlyph[i] != -1)
|
|
|
1de50a9 |
+ int gi = mvChar2BaseGlyph[i];
|
|
|
1de50a9 |
+ if (gi != -1)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- if (
|
|
|
1de50a9 |
+ if (!mvGlyphs[gi].IsDiacritic() &&
|
|
|
1de50a9 |
(mvCharBreaks[i] > -35 || (mvCharBreaks[i-1] > 0 && mvCharBreaks[i-1] < 35)) &&
|
|
|
1de50a9 |
- (mvCharBreaks[i-1] < 35 || (mvCharBreaks[i] < 0 && mvCharBreaks[i] > -35))
|
|
|
1de50a9 |
- )
|
|
|
1de50a9 |
+ (mvCharBreaks[i-1] < 35 || (mvCharBreaks[i] < 0 && mvCharBreaks[i] > -35)))
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
nLastBreak = static_cast<int>(i);
|
|
|
1de50a9 |
wLastBreak = nWidth;
|
|
|
1de50a9 |
@@ -755,10 +537,6 @@ DeviceCoordinate GraphiteLayout::FillDXArray( DeviceCoordinate* pDXArray ) const
|
|
|
1de50a9 |
fprintf(grLog(),"%d,%d,%ld ", (int)i, (int)mvCharDxs[i], pDXArray[i]);
|
|
|
1de50a9 |
#endif
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
- //std::adjacent_difference(mvCharDxs.begin(), mvCharDxs.end(), pDXArray);
|
|
|
1de50a9 |
- //for (size_t i = 0; i < mvCharDxs.size(); i++)
|
|
|
1de50a9 |
- // fprintf(grLog(),"%d,%d,%d ", (int)i, (int)mvCharDxs[i], pDXArray[i]);
|
|
|
1de50a9 |
- //fprintf(grLog(),"FillDX %ld,%d\n", mnWidth, std::accumulate(pDXArray, pDXArray + mvCharDxs.size(), 0));
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
fprintf(grLog(),"FillDXArray %d-%d=%g\n", mnMinCharPos, mnEndCharPos, (double)mnWidth);
|
|
|
1de50a9 |
@@ -769,7 +547,7 @@ DeviceCoordinate GraphiteLayout::FillDXArray( DeviceCoordinate* pDXArray ) const
|
|
|
1de50a9 |
void GraphiteLayout::AdjustLayout(ImplLayoutArgs& rArgs)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
SalLayout::AdjustLayout(rArgs);
|
|
|
1de50a9 |
- if(rArgs.mpDXArray)
|
|
|
1de50a9 |
+ if(rArgs.mpDXArray && mvGlyphs.size())
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
std::vector<int> vDeltaWidths(mvGlyphs.size(), 0);
|
|
|
1de50a9 |
ApplyDXArray(rArgs, vDeltaWidths);
|
|
|
1de50a9 |
@@ -817,11 +595,14 @@ void GraphiteLayout::expandOrCondense(ImplLayoutArgs &rArgs)
|
|
|
1de50a9 |
int nClusterCount = 0;
|
|
|
1de50a9 |
for (size_t j = 0; j < mvGlyphs.size(); j++)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- if (mvGlyphs[j].IsClusterStart())
|
|
|
1de50a9 |
+ if (mvGlyphs[j].IsClusterStart() && !mvGlyphs[j].IsDiacritic())
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
++nClusterCount;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
+#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
+ fprintf(grLog(), "Expand by width %f for %ld clusters\n", nDeltaWidth, nClusterCount);
|
|
|
1de50a9 |
+#endif
|
|
|
1de50a9 |
if (nClusterCount > 1)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
float fExtraPerCluster = static_cast<float>(nDeltaWidth) / static_cast<float>(nClusterCount - 1);
|
|
|
1de50a9 |
@@ -829,7 +610,7 @@ void GraphiteLayout::expandOrCondense(ImplLayoutArgs &rArgs)
|
|
|
1de50a9 |
int nOffset = 0;
|
|
|
1de50a9 |
for (size_t i = 0; i < mvGlyphs.size(); i++)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- if (mvGlyphs[i].IsClusterStart())
|
|
|
1de50a9 |
+ if (mvGlyphs[i].IsClusterStart() && !mvGlyphs[i].IsDiacritic())
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
nOffset = static_cast<int>(fExtraPerCluster * nCluster);
|
|
|
1de50a9 |
int nCharIndex = mvGlyph2Char[i];
|
|
|
1de50a9 |
@@ -882,134 +663,126 @@ void GraphiteLayout::expandOrCondense(ImplLayoutArgs &rArgs)
|
|
|
1de50a9 |
mnWidth = rArgs.mnLayoutWidth;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
|
|
|
1de50a9 |
+unsigned int GraphiteLayout::ScanFwdForChar(int &findChar, bool fallback) const
|
|
|
1de50a9 |
+{
|
|
|
1de50a9 |
+ int res = mvChar2Glyph[findChar - mnMinCharPos];
|
|
|
1de50a9 |
+ int done = 3;
|
|
|
1de50a9 |
+ while (res == -1 && --done)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ if (fallback)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ for (++findChar; findChar - mnMinCharPos < int(mvChar2Glyph.size()); ++findChar)
|
|
|
1de50a9 |
+ if ((res = mvChar2Glyph[findChar - mnMinCharPos]) != -1)
|
|
|
1de50a9 |
+ return res;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+ else
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ for (--findChar; findChar >= mnMinCharPos; --findChar)
|
|
|
1de50a9 |
+ if ((res = mvChar2Glyph[findChar - mnMinCharPos]) != -1)
|
|
|
1de50a9 |
+ return res;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+ fallback = !fallback;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+ return unsigned(res);
|
|
|
1de50a9 |
+}
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDeltaWidth)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- const size_t nChars = args.mnEndCharPos - args.mnMinCharPos;
|
|
|
1de50a9 |
- if (nChars == 0) return;
|
|
|
1de50a9 |
+ bool bRtl(mnLayoutFlags & SalLayoutFlags::BiDiRtl);
|
|
|
1de50a9 |
+ int startChar = args.mnMinCharPos < mnMinCharPos ? mnMinCharPos : args.mnMinCharPos;
|
|
|
1de50a9 |
+ int endChar = args.mnEndCharPos >= mnEndCharPos ? mnEndCharPos - 1 : args.mnEndCharPos;
|
|
|
1de50a9 |
+ unsigned int startGi = ScanFwdForChar(startChar, !bRtl);
|
|
|
1de50a9 |
+ unsigned int endGi = ScanFwdForChar(endChar, bRtl);
|
|
|
1de50a9 |
+ int nChars = endChar - startChar + 1;
|
|
|
1de50a9 |
+ if (nChars <= 0) return;
|
|
|
1de50a9 |
+ if (startGi > endGi)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ unsigned int temp = endGi;
|
|
|
1de50a9 |
+ endGi = startGi;
|
|
|
1de50a9 |
+ startGi = temp;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+ ++endGi;
|
|
|
1de50a9 |
|
|
|
1de50a9 |
#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
for (size_t iDx = 0; iDx < mvCharDxs.size(); iDx++)
|
|
|
1de50a9 |
fprintf(grLog(),"%d,%d,%ld ", (int)iDx, (int)mvCharDxs[iDx], args.mpDXArray[iDx]);
|
|
|
1de50a9 |
- fprintf(grLog(),"ApplyDx\n");
|
|
|
1de50a9 |
+ fprintf(grLog(),"ApplyDx %d-%d=%d-%d\n", startChar, endChar, startGi, endGi);
|
|
|
1de50a9 |
#endif
|
|
|
1de50a9 |
- bool bRtl(mnLayoutFlags & SalLayoutFlags::BiDiRtl);
|
|
|
1de50a9 |
- int nXOffset = 0;
|
|
|
1de50a9 |
- if (bRtl)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- nXOffset = args.mpDXArray[nChars - 1] - mvCharDxs[nChars - 1];
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- int nPrevClusterGlyph = (bRtl)? (signed)mvGlyphs.size() : -1;
|
|
|
1de50a9 |
- int nPrevClusterLastChar = -1;
|
|
|
1de50a9 |
- for (size_t i = 0; i < nChars; i++)
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ for (unsigned int i = startGi; i < endGi; ++i)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- int nChar2Base = mvChar2BaseGlyph[i];
|
|
|
1de50a9 |
- if ((nChar2Base > -1) && (nChar2Base != nPrevClusterGlyph))
|
|
|
1de50a9 |
+ // calculate visual cluster bounds
|
|
|
1de50a9 |
+ int firstChar = mvGlyph2Char[i];
|
|
|
1de50a9 |
+ unsigned int nBaseGlyph = mvChar2BaseGlyph[firstChar - mnMinCharPos];
|
|
|
1de50a9 |
+ while (nBaseGlyph == ~0U && i < endGi)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- assert((nChar2Base > -1) && (nChar2Base < (signed)mvGlyphs.size()));
|
|
|
1de50a9 |
- GlyphItem & gi = mvGlyphs[nChar2Base];
|
|
|
1de50a9 |
- if (!gi.IsClusterStart())
|
|
|
1de50a9 |
- continue;
|
|
|
1de50a9 |
-
|
|
|
1de50a9 |
- // find last glyph of this cluster
|
|
|
1de50a9 |
- size_t j = i + 1;
|
|
|
1de50a9 |
- int nLastChar = i;
|
|
|
1de50a9 |
- int nLastGlyph = nChar2Base;
|
|
|
1de50a9 |
- for (; j < nChars; j++)
|
|
|
1de50a9 |
+ ++i;
|
|
|
1de50a9 |
+ firstChar = mvGlyph2Char[i];
|
|
|
1de50a9 |
+ nBaseGlyph = unsigned(mvChar2BaseGlyph[firstChar - mnMinCharPos]);
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+ int lastChar = firstChar;
|
|
|
1de50a9 |
+ unsigned int nLastGlyph = i;
|
|
|
1de50a9 |
+ // firstGlyph = i
|
|
|
1de50a9 |
+ for ( ; nLastGlyph < endGi; nLastGlyph++)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ int thisChar = mvGlyph2Char[nLastGlyph];
|
|
|
1de50a9 |
+ if (thisChar == -1) continue;
|
|
|
1de50a9 |
+ if (unsigned(mvChar2BaseGlyph[thisChar - mnMinCharPos]) != nBaseGlyph)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- const int nChar2BaseJ = mvChar2BaseGlyph[j];
|
|
|
1de50a9 |
- assert((nChar2BaseJ >= -1) && (nChar2BaseJ < (signed)mvGlyphs.size()));
|
|
|
1de50a9 |
- if (nChar2BaseJ != -1 )
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- nLastGlyph = nChar2BaseJ + ((bRtl)? +1 : -1);
|
|
|
1de50a9 |
- nLastChar = j - 1;
|
|
|
1de50a9 |
+ if (!mvGlyphs[nLastGlyph].IsDiacritic())
|
|
|
1de50a9 |
break;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- if (nLastGlyph < 0)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- nLastGlyph = nChar2Base;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- // Its harder to find the last glyph rtl, since the first of
|
|
|
1de50a9 |
- // cluster is still on the left so we need to search towards
|
|
|
1de50a9 |
- // the previous cluster to the right
|
|
|
1de50a9 |
- if (bRtl)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- nLastGlyph = nChar2Base;
|
|
|
1de50a9 |
- while (nLastGlyph + 1 < (signed)mvGlyphs.size() &&
|
|
|
1de50a9 |
- !mvGlyphs[nLastGlyph+1].IsClusterStart())
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- ++nLastGlyph;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- if (j == nChars)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- nLastChar = nChars - 1;
|
|
|
1de50a9 |
- if (!bRtl) nLastGlyph = mvGlyphs.size() - 1;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- int nBaseCount = 0;
|
|
|
1de50a9 |
- // count bases within cluster - may be more than 1 with reordering
|
|
|
1de50a9 |
- for (int k = nChar2Base; k <= nLastGlyph; k++)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- if (mvGlyphs[k].IsClusterStart()) ++nBaseCount;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- assert((nLastChar > -1) && (nLastChar < (signed)nChars));
|
|
|
1de50a9 |
- long nNewClusterWidth = args.mpDXArray[nLastChar];
|
|
|
1de50a9 |
- long nOrigClusterWidth = mvCharDxs[nLastChar];
|
|
|
1de50a9 |
- long nDGlyphOrigin = 0;
|
|
|
1de50a9 |
- if (nPrevClusterLastChar > - 1)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- assert(nPrevClusterLastChar < (signed)nChars);
|
|
|
1de50a9 |
- nNewClusterWidth -= args.mpDXArray[nPrevClusterLastChar];
|
|
|
1de50a9 |
- nOrigClusterWidth -= mvCharDxs[nPrevClusterLastChar];
|
|
|
1de50a9 |
- nDGlyphOrigin = args.mpDXArray[nPrevClusterLastChar] - mvCharDxs[nPrevClusterLastChar];
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- long nDWidth = nNewClusterWidth - nOrigClusterWidth;
|
|
|
1de50a9 |
-#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
- fprintf(grLog(), "c%lu last glyph %d/%lu\n", i, nLastGlyph, mvGlyphs.size());
|
|
|
1de50a9 |
-#endif
|
|
|
1de50a9 |
- assert((nLastGlyph > -1) && (nLastGlyph < (signed)mvGlyphs.size()));
|
|
|
1de50a9 |
- mvGlyphs[nLastGlyph].mnNewWidth += nDWidth;
|
|
|
1de50a9 |
- if (gi.maGlyphId != GF_DROPPED)
|
|
|
1de50a9 |
- mvGlyphs[nLastGlyph].mnNewWidth += nDWidth;
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- nDGlyphOrigin += nDWidth;
|
|
|
1de50a9 |
- long nDOriginPerBase = (nBaseCount > 0)? nDWidth / nBaseCount : 0;
|
|
|
1de50a9 |
- nBaseCount = -1;
|
|
|
1de50a9 |
- // update glyph positions
|
|
|
1de50a9 |
- if (bRtl)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- for (int n = nChar2Base; n <= nLastGlyph; n++)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- if (mvGlyphs[n].IsClusterStart()) ++nBaseCount;
|
|
|
1de50a9 |
- assert((n > - 1) && (n < (signed)mvGlyphs.size()));
|
|
|
1de50a9 |
- mvGlyphs[n].maLinearPos.X() += -(nDGlyphOrigin + nDOriginPerBase * nBaseCount) + nXOffset;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
- else
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- for (int n = nChar2Base; n <= nLastGlyph; n++)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- if (mvGlyphs[n].IsClusterStart()) ++nBaseCount;
|
|
|
1de50a9 |
- assert((n > - 1) && (n < (signed)mvGlyphs.size()));
|
|
|
1de50a9 |
- mvGlyphs[n].maLinearPos.X() += nDGlyphOrigin + (nDOriginPerBase * nBaseCount) + nXOffset;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
+ else
|
|
|
1de50a9 |
+ nBaseGlyph = mvChar2BaseGlyph[thisChar - mnMinCharPos];
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
- rDeltaWidth[nChar2Base] = nDWidth;
|
|
|
1de50a9 |
+ if (thisChar > lastChar) lastChar = thisChar;
|
|
|
1de50a9 |
+ if (thisChar < firstChar) firstChar = thisChar;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ // calculate visual cluster widths
|
|
|
1de50a9 |
+ if (lastChar > args.mnEndCharPos) lastChar = args.mnEndCharPos;
|
|
|
1de50a9 |
+ if (firstChar < args.mnMinCharPos) firstChar = args.mnMinCharPos;
|
|
|
1de50a9 |
+ long nOrigClusterWidth = mvCharDxs[lastChar - mnMinCharPos];
|
|
|
1de50a9 |
+ long nNewClusterWidth = args.mpDXArray[lastChar - args.mnMinCharPos];
|
|
|
1de50a9 |
+ long nDGlyphOrigin = 0;
|
|
|
1de50a9 |
+ if (firstChar > args.mnMinCharPos)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ //nNewClusterWidth -= args.mpDXArray[firstChar - args.mnMinCharPos];
|
|
|
1de50a9 |
+ //nOrigClusterWidth -= mvCharDxs[firstChar - mnMinCharPos];
|
|
|
1de50a9 |
+ nDGlyphOrigin = args.mpDXArray[firstChar - args.mnMinCharPos - 1]
|
|
|
1de50a9 |
+ - mvCharDxs[firstChar - mnMinCharPos - 1];
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ // update visual cluster
|
|
|
1de50a9 |
+ long nDWidth = nNewClusterWidth - nOrigClusterWidth;
|
|
|
1de50a9 |
+ if (firstChar >= args.mnMinCharPos)
|
|
|
1de50a9 |
+ for (int n = firstChar; n <= lastChar; ++n)
|
|
|
1de50a9 |
+ if (n > mnMinCharPos && mvCharDxs[n - mnMinCharPos - 1] != -1)
|
|
|
1de50a9 |
+ mvCharDxs[n - mnMinCharPos - 1] += nDGlyphOrigin; // + nDWidth;
|
|
|
1de50a9 |
+ for (unsigned int n = i; n < nLastGlyph; n++)
|
|
|
1de50a9 |
+ //mvGlyphs[n].maLinearPos.X() += (nDGlyphOrigin + nDWidth) * (bRtl ? -1 : 1);
|
|
|
1de50a9 |
+ mvGlyphs[n].maLinearPos.X() += nDGlyphOrigin * (bRtl ? -1 : 1);
|
|
|
1de50a9 |
+
|
|
|
1de50a9 |
+ rDeltaWidth[nBaseGlyph] = nDWidth;
|
|
|
1de50a9 |
#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
- 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());
|
|
|
1de50a9 |
+ fprintf(grLog(),"c%d=%d g%d-%d dW%ld-%ld=%ld dX%ld x%ld @%d=%d\n", firstChar, lastChar, i, nLastGlyph, nNewClusterWidth, nOrigClusterWidth, nDWidth, nDGlyphOrigin, mvGlyphs[i].maLinearPos.X(), mvCharDxs[lastChar - mnMinCharPos], args.mpDXArray[lastChar - args.mnMinCharPos]);
|
|
|
1de50a9 |
#endif
|
|
|
1de50a9 |
- nPrevClusterGlyph = nChar2Base;
|
|
|
1de50a9 |
- nPrevClusterLastChar = nLastChar;
|
|
|
1de50a9 |
- i = nLastChar;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
+ i = nLastGlyph - 1;
|
|
|
1de50a9 |
+ if (i >= endGi - 1)
|
|
|
1de50a9 |
+ mnWidth += nDGlyphOrigin + nDWidth;
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
// Update the dx vector with the new values.
|
|
|
1de50a9 |
std::copy(args.mpDXArray, args.mpDXArray + nChars,
|
|
|
1de50a9 |
mvCharDxs.begin() + (args.mnMinCharPos - mnMinCharPos));
|
|
|
1de50a9 |
+ //args.mpDXArray[0] = 0;
|
|
|
1de50a9 |
#ifdef GRLAYOUT_DEBUG
|
|
|
1de50a9 |
fprintf(grLog(),"ApplyDx %ld(%ld)\n", args.mpDXArray[nChars - 1], mnWidth);
|
|
|
1de50a9 |
#endif
|
|
|
1de50a9 |
- mnWidth = args.mpDXArray[nChars - 1];
|
|
|
1de50a9 |
+ if (bRtl)
|
|
|
1de50a9 |
+ {
|
|
|
1de50a9 |
+ int diff = mvGlyphs[0].maLinearPos.X();
|
|
|
1de50a9 |
+ for (size_t i = 0; i < mvGlyphs.size(); ++i)
|
|
|
1de50a9 |
+ mvGlyphs[i].maLinearPos.X() -= diff;
|
|
|
1de50a9 |
+ }
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
|
|
|
1de50a9 |
void GraphiteLayout::kashidaJustify(std::vector<int>& rDeltaWidths, sal_GlyphId nKashidaIndex, int nKashidaWidth)
|
|
|
1de50a9 |
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
|
|
|
1de50a9 |
index d1515a1..261e1b0 100644
|
|
|
1de50a9 |
--- a/vcl/win/source/gdi/winlayout.cxx
|
|
|
1de50a9 |
+++ b/vcl/win/source/gdi/winlayout.cxx
|
|
|
1de50a9 |
@@ -2374,11 +2374,6 @@ GraphiteWinLayout::~GraphiteWinLayout()
|
|
|
1de50a9 |
|
|
|
1de50a9 |
bool GraphiteWinLayout::LayoutText( ImplLayoutArgs & args)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
- if (args.mnMinCharPos >= args.mnEndCharPos)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- maImpl.clear();
|
|
|
1de50a9 |
- return true;
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
HFONT hUnRotatedFont = 0;
|
|
|
1de50a9 |
if (args.mnOrientation)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
@@ -2392,15 +2387,7 @@ bool GraphiteWinLayout::LayoutText( ImplLayoutArgs & args)
|
|
|
1de50a9 |
}
|
|
|
1de50a9 |
WinLayout::AdjustLayout(args);
|
|
|
1de50a9 |
maImpl.SetFontScale(WinLayout::mfFontScale);
|
|
|
1de50a9 |
- gr_segment * pSegment = maImpl.CreateSegment(args);
|
|
|
1de50a9 |
- bool bSucceeded = false;
|
|
|
1de50a9 |
- if (pSegment)
|
|
|
1de50a9 |
- {
|
|
|
1de50a9 |
- // replace the DC on the font within the segment
|
|
|
1de50a9 |
- // create glyph vectors
|
|
|
1de50a9 |
- bSucceeded = maImpl.LayoutGlyphs(args, pSegment);
|
|
|
1de50a9 |
- gr_seg_destroy(pSegment);
|
|
|
1de50a9 |
- }
|
|
|
1de50a9 |
+ bool bSucceeded = maImpl.LayoutText(args);
|
|
|
1de50a9 |
if (args.mnOrientation)
|
|
|
1de50a9 |
{
|
|
|
1de50a9 |
// restore the rotated font
|
|
|
1de50a9 |
--
|
|
|
1de50a9 |
2.7.1
|
|
|
1de50a9 |
|