#include "GuiGraphicsUniscribe.h"
#pragma comment(lib,
"usp10.lib"
)
namespace
{
namespace
{
namespace
{
using
namespace
regex
;
::
(
const
&
)
:text(
)
{
.
(
(
0
,
.
()),
(
(
0
,
0
,
0
),
(
0
,
0
,
0
,
0
)));
}
::
()
{
return
.
+
L"#"
+
(
.
)+
L"#"
+(
.
?
L"B"
:
L"N"
)+
L"#"
+(
.
?
L"I"
:
L"N"
)+
L"#"
+(
.
?
L"U"
:
L"N"
)+
L"#"
+(
.
?
L"S"
:
L"N"
)+
L"#"
;
}
void
::
(
,
)
{
=
+
;
for
(
=
.
()-
1
;
i
>=
0
;
i
--)
{
=
.
()
i
];
if
(
key
.
<
end
&&
<
key
.
)
{
=
.
()
i
];
=
key
.
;
=
key
.
>
?
key
.
:
;
=
key
.
<
end
?
key
.
:
end
;
=
key
.
;
.
(
key
);
if
(
s1
<
s2
)
{
.
(
(
s1
,
s2
),
value
);
}
if
(
s2
<
s3
)
{
.
(
(
s2
,
s3
),
value
);
}
if
(
s3
<
s4
)
{
.
(
(
s3
,
s4
),
value
);
}
}
}
}
void
::
(
,
,
::*
,
)
{
=
+
;
for
(
=
.
()-
1
;
i
>=
0
;
i
--)
{
=
.
()
i
];
if
(
key
.
<
end
&&
<
key
.
)
{
=
.
()
i
];
value
.*
;
.
(
key
,
value
);
}
}
}
void
::
()
{
=-
1
;
;
for
(
=
.
()-
1
;
i
>=-
1
;
i
--)
{
if
(
lastIndex
==-
1
)
{
lastIndex
=
i
;
if
(
i
!=-
1
)
{
lastColor
.
()
i
];
}
}
else
if
(
i
==-
1
||
.
()
i
]!=
lastColor
)
{
if
(
lastIndex
-
i
>
0
)
{
=
.
()
i
+
1
].
;
=
.
()
lastIndex
].
;
(
start
,
end
);
for
(
=
lastIndex
;
j
>
i
;
j
--)
{
.
(
.
()
j
]);
}
.
(
key
,
lastColor
);
}
lastIndex
=
i
;
if
(
i
!=-
1
)
{
lastColor
.
()
i
];
}
}
}
}
::
(
)
{
=
0
;
=
.
()-
1
;
while
(
start
<=
end
)
{
=(
start
+
end
)/
2
;
=
.
()
middle
];
if
(
<
key
.
)
{
end
=
middle
-
1
;
}
else
if
(
>=
key
.
)
{
start
=
middle
+
1
;
}
else
{
return
.
()
middle
];
}
}
return
();
}
<
>
::
(
,
)
{
=
+
;
<
>
=
new
(
==
0
?
L""
:
.
(
,
));
fragment
;
fragment
;
if
(
!=
0
)
{
fragment
.
();
(
,
);
for
(
=
0
;
i
<
.
();
i
++)
{
=
.
()
i
];
if
(
key
.
<
end
&&
<
key
.
)
{
=
.
()
i
];
fragment
.
(
(
key
.
-
,
key
.
-
),
value
);
}
}
}
return
fragment
;
}
::
()
{
(
0
,
0
);
}
void
::
(
,
)
{
.
(
);
.
(
);
.
(
);
.
(
);
.
(
);
(&
,
0
,
sizeof
(
));
(&
,
0
,
sizeof
(
));
}
bool
::
(
*
,
*
,
&
,
const
wchar_t
*
,
,
<
>&
,
<
bool
>&
)
{
=
.
();
bool
=
false
;
if
(
glyphCount
==
0
)
{
glyphCount
=(
)(
1.5
*
+
16
);
resizeGlyphData
=
true
;
}
->
;
*
=
0
;
{
if
(
resizeGlyphData
)
{
.
(
glyphCount
);
.
(
glyphCount
);
.
(
);
}
while
(
true
)
{
int
=
0
;
=
(
(dcParameter?dcParameter->GetHandle():NULL),
(
dcParameter
?
dcParameter
->
():
0
),
&
,
,
(
int
)
,
(
int
)
glyphCount
,
&
,
&
0
],
&
0
],
&
0
],
&
availableGlyphCount
);
if
(
hr
==
0
)
{
glyphCount
=
availableGlyphCount
;
break
;
}
else if(hr==E_PENDING)
else
if
(
hr
==((
)
0x8000000AL
))
{
dcParameter
=
;
}
else if(hr==E_OUTOFMEMORY)
else
if
(
hr
==((
)
0x8007000EL
))
{
if
(
resizeGlyphData
)
{
glyphCount
+=
;
}
else
{
goto
BUILD_UNISCRIBE_DATA_FAILED;
}
}
else if(hr==USP_E_SCRIPT_NOT_IN_FONT)
else
if
(
hr
==((
) (((
unsigned
long
)(
1
)<<
31
) | ((
unsigned
long
)(
4
)<<
16
) | ((
unsigned
long
)(
0x200
))) ))
{
if(sa.eScript==SCRIPT_UNDEFINED)
{
goto
BUILD_UNISCRIBE_DATA_FAILED;
}
else
{
sa.eScript=SCRIPT_UNDEFINED;
}
}
else
{
goto
BUILD_UNISCRIBE_DATA_FAILED;
}
}
if
(
resizeGlyphData
)
{
.
(
glyphCount
);
.
(
glyphCount
);
}
}
{
;
(&
fp
,
0
,
sizeof
(
fp
));
fp
.
=
sizeof
(
fp
);
=
(
(dcParameter?dcParameter->GetHandle():NULL),
(
dcParameter
?
dcParameter
->
():
0
),
&
,
&
fp
);
=
fp
.
;
{
invalidGlyph
=
0
;
}
.
(
0
);
=
0
;
bool
=
false
;
while
(
charIndex
<
)
{
=
charIndex
];
=
charIndex
;
while
(
nextCharIndex
<
&&
nextCharIndex
]==
glyphIndex
)
{
nextCharIndex
++;
}
=
0
;
if
(
nextCharIndex
==
)
{
glyphCount
=
.
()-
glyphIndex
;
}
else
{
glyphCount
=
nextCharIndex
]-
glyphIndex
;
}
if
(
->
.
)
{
glyphCount
=-
glyphCount
;
glyphIndex
-=
glyphCount
-
1
;
}
bool
=
true
;
for
(
=
0
;
i
<
glyphCount
;
i
++)
{
if
(
i
+
glyphIndex
]==
invalidGlyph
)
{
available
=
false
;
}
}
if
(
charIndex
==
0
)
{
lastGlyphAvailable
=
available
;
.
(
available
);
}
else
if
(
lastGlyphAvailable
!=
available
)
{
.
(
charIndex
);
lastGlyphAvailable
=
available
;
.
(
available
);
}
charIndex
=
nextCharIndex
;
}
}
if
(
.
()==
1
)
{
*
=
0
;
if
(
resizeGlyphData
)
{
.
(
glyphCount
);
.
(
glyphCount
);
}
while
(
true
)
{
=
(
(dcParameter?dcParameter->GetHandle():NULL),
(
dcParameter
?
dcParameter
->
():
0
),
&
,
&
0
],
(
int
)
glyphCount
,
&
0
],
&
,
&
0
],
&
0
],
&
);
if
(
hr
==
0
)
{
break
;
}
else if(hr==E_PENDING)
else
if
(
hr
==((
)
0x8000000AL
))
{
dcParameter
=
;
}
else
{
goto
BUILD_UNISCRIBE_DATA_FAILED;
}
}
}
return
true
;
BUILD_UNISCRIBE_DATA_FAILED:
return
false
;
}
void
::
(
*
,
*
,
*
,
const
wchar_t
*
,
)
{
=
0
;
for
(
=
0
;
i
<
;
i
++)
{
if
(
i
==
0
||
[
i
].
)
{
glyphCount
++;
}
}
(
glyphCount
,
);
->
;
(&
0
],
0
,
sizeof
(
0
])*
.
());
(&
0
],
0
,
sizeof
(
0
])*
.
());
(&
0
],
0
,
sizeof
(
0
])*
.
());
(&
0
],
0
,
sizeof
(
0
])*
.
());
(&
0
],
0
,
sizeof
(
0
])*
.
());
for
(
=
0
;
i
<
glyphCount
;
i
++)
{
i
]=(
)
i
;
}
if
(
.
)
{
=
0
;
for
(
=
0
;
i
<
;
i
++)
{
if
(
i
==
0
||
[
i
].
)
{
currentGlyphCount
++;
}
i
]=(
)(
glyphCount
-
currentGlyphCount
);
}
}
else
{
=
0
;
for
(
=
0
;
i
<
;
i
++)
{
if
(
i
==
0
||
[
i
].
)
{
currentGlyphCount
++;
}
i
]=(
)(
currentGlyphCount
-
1
);
}
}
{
=
0
;
=
0
;
for
(
=
1
;
i
<=
;
i
++)
{
if
(
i
==
0
||
[
i
].
)
{
=
i
-
lastCharIndex
;
const
wchar_t
*
=
.
?
+
-
lastCharIndex
-
glyphLength
:
+
lastCharIndex
;
=
->
(
,
glyphLength
, -
1
);
lastGlyphIndex
]=
size
.
;
lastCharIndex
=
i
;
lastGlyphIndex
++;
}
}
}
for
(
=
0
;
i
<
glyphCount
;
i
++)
{
.
+=
i
];
}
}
::
()
:startFromLine(
0
)
,length(
0
)
,itemText(
0
)
{
}
::
()
{
}
void
::
()
{
.
(
0
);
}
bool
::
()
{
.
(
);
=
(
,
(
int
)
,
&
.
,
&
0
]
);
if
(
hr
!=
0
)
{
goto
BUILD_UNISCRIBE_DATA_FAILED;
}
return
true
;
BUILD_UNISCRIBE_DATA_FAILED:
();
return
false
;
}
bool
::
()
{
return
.
.
;
}
::
()
:documentFragment(
0
)
,scriptItem(
0
)
,startFromLine(
0
)
,startFromFragment(
0
)
,length(
0
)
,runText(
0
)
{
}
::
()
{
}
::
()
:scriptCache(
0
)
,advance(
0
)
,needFontFallback(
false
)
{
}
::
()
{
();
}
void
::
()
{
if
(
)
{
(&
);
=
0
;
}
=
0
;
=
false
;
.
(
0
,
0
);
}
void
::
(
,
&
,
&
,
&
)
{
=
.
];
=
;
while
(
nextChar
<
.
.
())
{
if
(
.
nextChar
]!=
)
{
break
;
}
nextChar
++;
}
=
nextChar
-
;
(
,
,
,
);
}
void
::
(
,
&
,
&
,
&
)
{
=
0
;
=
+
-
->
;
=
startFromItem
;
while
(++
currentFromItem
<
->
)
{
if
(
->
currentFromItem
].
)
{
break
;
}
}
=
currentFromItem
-
startFromItem
;
(
,
,
,
);
}
void
::
(
,
,
&
,
&
)
{
=
.
];
if
(
+
>
)
{
=
-
;
}
if
(
->
())
{
=
+
==
?-
1
:
.
+
];
}
else
{
=
+
==
?
.
.
()
:
.
+
];
}
}
bool
::
(
*
,
<
>&
)
{
();
->
(
->
);
<
bool
>
;
if
(!
.
(
, &
->
,
,
,
,
,
breakingAvailabilities
))
{
goto
BUILD_UNISCRIBE_DATA_FAILED;
}
if
(
.
()==
1
&& !
breakingAvailabilities
0
])
{
*
=&
->
0
]+
-
->
;
.
(
, &
->
,
charLogattrs
,
,
);
=
true
;
}
=
.
.
+
.
.
+
.
.
;
return
true
;
BUILD_UNISCRIBE_DATA_FAILED:
();
return
false
;
}
::
(
,
)
{
=
0
;
=
0
;
(
,
,
cluster
,
nextCluster
);
=
0
;
if
(
->
())
{
for
(
=
cluster
;
i
>
nextCluster
;
i
--)
{
width
+=
.
i
];
}
}
else
{
for
(
=
cluster
;
i
<
nextCluster
;
i
++)
{
width
+=
.
i
];
}
}
return
width
;
}
::
()
{
return
->
.
;
}
::
()
{
return
();
}
void
::
(
,
,
bool
,
&
,
&
)
{
=
0
;
=
0
;
=
0
;
for
(
=
;
i
<=
;)
{
if(i==length || scriptItem->charLogattrs[i+(startFromLine-scriptItem->startFromLine)].fSoftBreak==TRUE)
if
(
i
==
||
->
i
+(
-
->
)].
==
1
)
{
if
(
width
<=
|| (
&&
==
0
))
{
=
i
-
;
=
width
;
}
else
{
return
;
}
}
if
(
i
==
)
break
;
=
.
i
];
=
1
;
while
(
i
+
clusterLength
<
)
{
if
(
.
i
+
clusterLength
]==
cluster
)
{
clusterLength
++;
}
else
{
break
;
}
}
if
(
->
())
{
=
i
+
clusterLength
==
?-
1
:
.
i
+
clusterLength
];
for
(
=
cluster
;
j
>
nextCluster
;
j
--)
{
width
+=
.
j
];
}
}
else
{
=
i
+
clusterLength
==
?
.
.
()
:
.
i
+
clusterLength
];
for
(
=
cluster
;
j
<
nextCluster
;
j
++)
{
width
+=
.
j
];
}
}
i
+=
clusterLength
;
}
}
void
::
(
*
,
,
,
,
bool
)
{
auto
=
->
();
&
=
];
if
(
fragment
.
==
0
)
return
;
=
0
;
=
0
;
while
(
startFromFragmentBounds
<
fragment
.
)
{
=
fragment
.
+
startFromFragmentBounds
;
=
0
;
=
0
;
=
0
;
(
charIndex
,
charLength
,
cluster
,
nextCluster
);
=
0
;
=
0
;
if
(
->
())
{
clusterStart
=
nextCluster
+
1
;
clusterCount
=
cluster
-
nextCluster
;
}
else
{
clusterStart
=
cluster
;
clusterCount
=
nextCluster
-
cluster
;
}
=
0
;
for
(
=
0
;
i
<
clusterCount
;
i
++)
{
clusterWidth
+=
.
i
+
clusterStart
];
}
=
0
;
if
(
->
())
{
x
=
fragment
.
.
-
accumulatedWidth
-
clusterWidth
;
}
else
{
x
=
fragment
.
.
+
accumulatedWidth
;
}
;
rect
.
=(
int
)(
x
+
);
rect
.
=(
int
)(
fragment
.
.
()+
);
rect
.
=(
int
)(
rect
.
+
clusterWidth
);
rect
.
=(
int
)(
rect
.
+
fragment
.
.
()*
1.5
);
=
->
(
charIndex
+
);
if
(
)
{
=
color
.
;
if
(
backgroundColor
.
>
0
)
{
Ptr<WinBrush> brush=new WinBrush(RGB(backgroundColor.r, backgroundColor.g, backgroundColor.b));
<
>
=
new
(((
)(((
)(
backgroundColor
.
)|((
)((
)(
backgroundColor
.
))<<
8
))|(((
)(
)(
backgroundColor
.
))<<
16
))));
dc
->
(
brush
);
dc
->
(
rect
);
}
}
else
{
=
color
.
;
dc
->
(
->
);
dc->SetTextColor(RGB(fontColor.r, fontColor.g, fontColor.b));
dc
->
(((
)(((
)(
fontColor
.
)|((
)((
)(
fontColor
.
))<<
8
))|(((
)(
)(
fontColor
.
))<<
16
))));
if
(
)
{
dc
->
(
rect
.
,
rect
.
,
+
charIndex
,
charLength
);
}
else
{
=
(
dc
->
(),
&
,
rect
.
,
rect
.
,
0
,
&
rect
,
&
.
,
0
,
&
.
clusterStart
],
(
int
)(
clusterCount
),
&
.
clusterStart
],
&
.
clusterStart
]
);
}
}
startFromFragmentBounds
+=
charLength
;
accumulatedWidth
+=
clusterWidth
;
}
}
UniscribeEmbeddedObjectRun
::
UniscribeEmbeddedObjectRun
()
{
}
UniscribeEmbeddedObjectRun
::
~
UniscribeEmbeddedObjectRun
()
{
}
bool
UniscribeEmbeddedObjectRun
::
(
*
,
<
>&
)
{
.
(
0
);
return
true
;
}
UniscribeEmbeddedObjectRun
::
(
,
)
{
return
.
.
;
}
UniscribeEmbeddedObjectRun
::
()
{
return
.
.
;
}
UniscribeEmbeddedObjectRun
::
()
{
return
0
;
}
void
UniscribeEmbeddedObjectRun
::
(
,
,
bool
,
&
,
&
)
{
if
(
||
.
.
<=
)
{
=
-
;
=
.
.
;
}
else
{
=
0
;
=
0
;
}
}
void
UniscribeEmbeddedObjectRun
::
(
*
,
,
,
,
bool
)
{
auto
=
->
();
&
=
];
if
(
)
{
;
rect
.
=(
int
)(
fragment
.
.
()+
)-
2
;
rect
.
=(
int
)(
fragment
.
.
()+
)-
2
;
rect
.
=(
int
)(
fragment
.
.
()+
)+
2
;
rect
.
=(
int
)(
fragment
.
.
()+
)+
2
;
=
->
.
()
0
].
;
if
(
backgroundColor
.
>
0
)
{
Ptr<WinBrush> brush=new WinBrush(RGB(backgroundColor.r, backgroundColor.g, backgroundColor.b));
<
>
=
new
(((
)(((
)(
backgroundColor
.
)|((
)((
)(
backgroundColor
.
))<<
8
))|(((
)(
)(
backgroundColor
.
))<<
16
))));
dc
->
(
brush
);
dc
->
(
rect
);
}
}
else
{
if
(
.
)
{
=
fragment
.
;
bounds
.
+=
;
bounds
.
+=
;
bounds
.
+=
;
bounds
.
+=
;
*
=
.
();
if
(
renderer
)
{
renderer
->
(
bounds
);
}
}
if
(
.
!= -
1
)
{
if
(
auto
=
->
())
{
auto
=
->
();
=
fragment
.
.
+
-
offset
.
;
=
fragment
.
.
+
-
offset
.
;
auto
=
paragraphCallback
->
(
.
,
(
(
x
,
y
),
fragment
.
.
()));
.
size
;
}
}
}
}
::
()
:startFromLine(
0
)
,length(
0
)
,runText(
0
)
,firstRunIndex(-
1
)
,firstRunBoundsIndex(-
1
)
,lastRunIndex(-
1
)
,lastRunBoundsIndex(-
1
)
{
}
::
()
:startFromParagraph(
0
)
{
}
void
::
()
{
.
();
.
();
.
();
}
bool
::
(
*
)
{
=
L""
;
();
=
0
;
<
>
;
FOREACH(Ptr<UniscribeFragment>, fragment, documentFragments)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
fragment
);)
{
fragmentStarts
.
(
current
);
fragment
text
;
current
+=
fragment
text
.
();
}
if
(
!=
L""
)
{
{
={
0
};
ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &sds);
ScriptRecordDigitSubstitution
((((
)((((
)((
)(
0x0
))) <<
16
) | ((
)((
)((((((
)(
0x01
)) <<
10
) | (
)(
0x00
))))))))), &
sds
);
={
0
};
={
0
};
ScriptApplyDigitSubstitution
(&
sds
, &
sc
, &
ss
);
<
>
(
.
()+
2
);
int
=
0
;
=
(
.
(),
(
int
)
.
(),
(
int
)(
items
.
()-
1
),
&
sc
,
&
ss
,
&
items
0
],
&
scriptItemCount
);
if
(
hr
!=
0
)
{
goto
BUILD_UNISCRIBE_DATA_FAILED;
}
items
.
(
scriptItemCount
+
1
);
for
(
=
0
;
i
<
scriptItemCount
;
i
++)
{
=
items
i
];
<
>
=
new
;
scriptItem
=
item
.
;
scriptItem
=
items
i
+
1
].
-
item
.
;
scriptItem
=
.
()+
item
.
;
scriptItem
item
;
if
(!
scriptItem
())
{
goto
BUILD_UNISCRIBE_DATA_FAILED;
}
.
(
scriptItem
);
}
}
{
=
0
;
=
0
;
for
(
=
0
;
i
<
.
();
i
++)
{
<
>
=
i
];
=
scriptItem
;
while
(
currentStart
<
scriptItem
+
scriptItem
)
{
*
=
0
;
=
scriptItem
-(
currentStart
-
scriptItem
);
=
0
;
while
(
true
)
{
fragment
=
fragmentIndex
].
();
fragmentRemainLength
=
fragment
->
text
.
()-(
currentStart
-
fragmentStart
);
if
(
fragmentRemainLength
<=
0
)
{
fragmentStart
+=
fragment
->
text
.
();
fragmentIndex
++;
}
else
{
break
;
}
}
=
itemRemainLength
<
fragmentRemainLength
?
itemRemainLength
:
fragmentRemainLength
;
bool
=
false
;
{
=
0
;
FOREACH(Ptr<UniscribeFragment>, elementFragment, documentFragments)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
elementFragment
);)
{
=
elementFragment
text
.
();
if
(
elementFragment
)
{
if
(
elementCurrent
<=
currentStart
&&
currentStart
+
shortLength
<=
elementCurrent
+
elementLength
)
{
if
(
elementCurrent
==
currentStart
)
{
auto
=
<
UniscribeEmbeddedObjectRun
>();
run
=
fragment
;
run
=
scriptItem
.
();
run
=
currentStart
;
run
=
currentStart
-
fragmentStarts
fragmentIndex
];
run
=
elementLength
;
run
=
.
()+
currentStart
;
run
elementFragment
.
();
.
(
run
);
}
skip
=
true
;
break
;
}
}
elementCurrent
+=
elementLength
;
}
}
if
(!
skip
)
{
<
>
=
new
;
run
=
fragment
;
run
=
scriptItem
.
();
run
=
currentStart
;
run
=
currentStart
-
fragmentStarts
fragmentIndex
];
run
=
shortLength
;
run
=
.
()+
currentStart
;
.
(
run
);
}
currentStart
+=
shortLength
;
}
}
=
0
;
while
(
runIndex
<
.
())
{
<
>
=
runIndex
];
<
>
;
if
(!
run
(
,
breakings
))
{
goto
BUILD_UNISCRIBE_DATA_FAILED;
}
else
if
(
breakings
.
()>
1
)
{
if
(
<
>
=
run
.
<
>())
{
.
(
runIndex
);
for
(
=
0
;
i
<
breakings
.
();
i
++)
{
=
breakings
i
];
=
i
==
breakings
.
()-
1
?
textRun
-
start
:
breakings
i
+
1
]-
start
;
<
>
=
new
;
newRun
=
run
;
newRun
=
run
;
newRun
=
start
+
run
;
newRun
=
start
+
run
;
newRun
=
length
;
newRun
=
run
+
newRun
-
run
;
.
(
runIndex
+
i
,
newRun
);
}
continue
;
}
}
runIndex
++;
}
}
}
return
true
;
BUILD_UNISCRIBE_DATA_FAILED:
();
return
false
;
}
void
::
(
,
,
,
&
)
{
=
0
;
=
;
.
();
if
(
.
()==
0
)
{
=(
)(
0
]
.
*
1.5
);
(
(
cx
,
cy
),
(
0
,
height
));
cy
+=
height
;
}
else
{
FOREACH(Ptr<UniscribeRun>, run, scriptRuns)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
run
);)
{
run
.
();
}
=
0
;
=
0
;
=
0
;
=
0
;
=
0
;
while
(
startRun
<
.
())
{
=
0
;
bool
=
true
;
for
(
=
startRun
;
i
<
.
();
i
++)
{
=
0
;
=
0
;
*
=
i
].
();
run
->
(
lastRunOffset
,
-
currentWidth
,
firstRun
,
charLength
,
charAdvances
);
firstRun
=
false
;
if
(
charLength
==
run
->
-
lastRunOffset
)
{
lastRun
=
i
+
1
;
lastRunOffset
=
0
;
currentWidth
+=
charAdvances
;
}
else
{
lastRun
=
i
;
lastRunOffset
=
lastRunOffset
+
charLength
;
break
;
}
}
if
(
startRun
<
lastRun
|| (
startRun
==
lastRun
&&
startRunOffset
<
lastRunOffset
))
{
=
lastRun
<
.
()-
1
?
lastRun
:
.
()-
1
;
=
0
;
=
0
;
for
(
=
startRun
;
i
<=
availableLastRun
;
i
++)
{
if
(
i
==
lastRun
&&
lastRunOffset
==
0
)
{
break
;
}
{
=
i
]
();
if
(
maxHeight
<
size
)
maxHeight
=
size
;
}
{
=
i
]
();
if
(
maxTextHeight
<
size
)
maxTextHeight
=
size
;
}
}
<
>
(
availableLastRun
-
startRun
+
1
);
<
int
>
(
levels
.
());
<
int
>
(
levels
.
());
for
(
=
startRun
;
i
<=
availableLastRun
;
i
++)
{
levels
i
-
startRun
]=
i
]
->
.
.
.
;
}
((
int
)
levels
.
(), &
levels
0
], &
runVisualToLogical
0
], &
runLogicalToVisual
0
]);
=-
1
;
for
(
=
startRun
;
i
<=
availableLastRun
;
i
++)
{
=
runVisualToLogical
i
-
startRun
]+
startRun
;
*
=
runIndex
].
();
=
runIndex
==
startRun
?
startRunOffset
:
0
;
=
runIndex
==
lastRun
?
lastRunOffset
:
run
->
;
=
end
-
start
;
if
(
runIndex
==
startRun
)
{
startRunFragmentCount
=
run
->
.
();
}
::
;
fragmentBounds
.
=
start
;
fragmentBounds
.
=
length
;
fragmentBounds
.
(
(
cx
,
cy
+
maxHeight
-
run
->
()),
(
run
->
(
start
,
length
),
run
->
())
);
run
->
.
(
fragmentBounds
);
cx
+=
run
->
(
start
,
length
);
}
=
0
;
switch
(
)
{
case
::
:
cxOffset
=(
-
cx
)/
2
;
break
;
case
::
:
cxOffset
=
-
cx
;
break
;
}
if
(
cxOffset
!=
0
)
{
for
(
=
startRun
;
i
<=
availableLastRun
;
i
++)
{
*
=
i
].
();
for
(
=(
i
==
startRun
?
startRunFragmentCount
:
0
);
j
<
run
->
.
();
j
++)
{
::
&
=
run
->
j
];
fragmentBounds
.
.
+=
cxOffset
;
fragmentBounds
.
.
+=
cxOffset
;
}
}
}
{
<
>
=
new
;
virtualLine
=
startRun
;
virtualLine
=
startRunFragmentCount
;
virtualLine
=
availableLastRun
;
virtualLine
=
availableLastRun
]
.
()-
1
;
*
=
virtualLine
].
();
*
=
virtualLine
].
();
::
&
=
firstRun
->
virtualLine
];
::
&
=
lastRun
->
virtualLine
];
virtualLine
=
firstRun
->
+
firstBounds
.
;
virtualLine
=
lastRun
->
+
lastBounds
.
+
lastBounds
.
-
virtualLine
;
virtualLine
=
.
()+
virtualLine
;
bool
=
false
;
for
(
=
startRun
;
i
<=
availableLastRun
;
i
++)
{
*
=
i
].
();
for
(
=(
i
==
startRun
?
startRunFragmentCount
:
0
);
j
<
run
->
.
();
j
++)
{
::
&
=
run
->
j
];
if
(
updateBounds
)
{
if
(
virtualLine
.
>
fragmentBounds
.
.
)
virtualLine
.
=
fragmentBounds
.
.
;
if
(
virtualLine
.
<
fragmentBounds
.
.
)
virtualLine
.
=
fragmentBounds
.
.
;
if
(
virtualLine
.
>
fragmentBounds
.
.
)
virtualLine
.
=
fragmentBounds
.
.
;
if
(
virtualLine
.
<
fragmentBounds
.
.
)
virtualLine
.
=
fragmentBounds
.
.
;
}
else
{
virtualLine
fragmentBounds
.
;
updateBounds
=
true
;
}
}
}
.
(
virtualLine
);
}
cx
=
0
;
cy
+=(
)(
maxHeight
+
maxTextHeight
*
0.5
);
}
startRun
=
lastRun
;
startRunOffset
=
lastRunOffset
;
}
=
0
;
=
;
=
0
;
=
;
FOREACH(Ptr<UniscribeRun>, run, scriptRuns)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
run
);)
{
FOREACH(UniscribeRun::RunFragmentBounds, fragmentBounds, run->fragmentBounds)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
::
>&
= ::
vl
::
collections
::
(
run
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
::
;
__foreach_iterator__
.
(
fragmentBounds
);)
{
=
fragmentBounds
.
;
if
(
minX
>
bounds
.
())
minX
=
bounds
.
();
if
(
minY
>
bounds
.
())
minX
=
bounds
.
();
if
(
maxX
<
bounds
.
())
maxX
=
bounds
.
();
if
(
maxY
<
bounds
.
())
maxY
=
bounds
.
();
}
}
(
minX
,
minY
,
maxX
,
maxY
);
}
=
cy
;
}
void
::
(
::
*
,
,
,
bool
)
{
FOREACH(Ptr<UniscribeRun>, run, scriptRuns)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
run
);)
{
for
(
=
0
;
i
<
run
.
();
i
++)
{
run
(
,
i
,
,
,
);
}
}
}
::
()
:lastAvailableWidth(-
1
)
,paragraphAlignment(
::
)
,built(
false
)
{
}
::
()
{
();
}
void
::
()
{
FOREACH(Ptr<UniscribeFragment>, fragment, documentFragments)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
fragment
);)
{
GetWindowsGDIResourceManager
()->
(
fragment
);
fragment
0
;
}
.
();
=-
1
;
}
bool
::
(
*
)
{
if
(
)
return
false
;
=
true
;
();
<
,
<
>>
;
FOREACH(Ptr<UniscribeFragment>, fragment, documentFragments)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
fragment
);)
{
if
(!
fragment
)
{
=
fragment
();
=
fonts
.
().
(
fragmentFingerPrint
);
if
(
index
==-
1
)
{
fragment
GetWindowsGDIResourceManager
()->
(
fragment
);
fonts
.
(
fragmentFingerPrint
,
fragment
);
}
else
{
fragment
fonts
.
().
(
index
);
}
}
}
{
(
L"\r\n"
);
<
>
;
FOREACH(Ptr<UniscribeFragment>, fragment, documentFragments)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
fragment
);)
{
if
(
fragment
)
{
if
(!
line
)
{
line
new
;
.
(
line
);
}
line
.
(
fragment
);
}
else
{
::
;
regexLine
.
(
fragment
text
,
true
,
textLines
);
for
(
=
0
;
i
<
textLines
.
();
i
++)
{
=
textLines
i
]
();
=
rs
.
();
if
(
i
>
0
)
{
line
0
;
}
if
(!
line
)
{
line
new
;
.
(
line
);
}
if
(
textLines
.
()==
1
)
{
line
.
(
fragment
);
}
else
{
<
>
=
fragment
(
rs
.
(),
rs
.
());
line
.
(
runFragment
);
}
}
}
}
}
FOREACH(Ptr<UniscribeLine>, line, lines)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
line
);)
{
line
(
);
}
=
0
;
FOREACH(Ptr<UniscribeLine>, line, lines)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
line
);)
{
line
=
lineStart
;
lineStart
+=
line
.
()+
2
;
}
return
true
;
}
void
::
(
,
)
{
if
(
==
&&
==
)
{
return
;
}
=
;
=
;
=
0
;
FOREACH(Ptr<UniscribeLine>, line, lines)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
line
);)
{
line
(
,
,
cy
,
cy
);
}
=
0
;
=
0
;
=
0
;
=
0
;
FOREACH(Ptr<UniscribeLine>, line, lines)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
line
);)
{
=
line
;
if
(
minX
>
bounds
.
())
minX
=
bounds
.
();
if
(
minY
>
bounds
.
())
minX
=
bounds
.
();
if
(
maxX
<
bounds
.
())
maxX
=
bounds
.
();
if
(
maxY
<
bounds
.
())
maxY
=
bounds
.
();
}
=
0
;
FOREACH(Ptr<UniscribeLine>, line, lines)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
line
);)
{
FOREACH(Ptr<UniscribeFragment>, fragment, line->documentFragments)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
line
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
fragment
);)
{
=
fragment
.
/
3
;
if
(
size
>
offsetY
)
{
offsetY
=
size
;
}
}
}
(
minX
,
minY
,
maxX
,
maxY
+
offsetY
);
}
void
::
(
::
*
,
bool
)
{
auto
=
->
();
FOREACH(Ptr<UniscribeLine>, line, lines)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
line
);)
{
line
(
,
offset
.
,
offset
.
,
);
}
}
void
::
(
,
,
&
,
&
,
&
,
&
)
{
=-
1
;
=-
1
;
=-
1
;
=-
1
;
=
0
;
for
(
=
0
;
i
<
.
();
i
++)
{
=
i
]
text
.
();
if
(
current
<=
&&
<
current
+
fragmentLength
)
{
=
i
;
=
-
current
;
}
if
(
current
<=
+
&&
+
<=
current
+
fragmentLength
)
{
=
i
;
=
+
-
current
;
}
if
(
!=-
1
&&
!=-
1
)
{
break
;
}
current
+=
fragmentLength
;
}
}
bool
::
(
,
,
,
,
&
,
&
)
{
=-
1
;
=-
1
;
if
(
==
)
{
<
>
=
];
if
(
fragment
)
{
if
(
==
0
&&
==
fragment
text
.
())
{
=
=
;
return
true
;
}
else
{
return
false
;
}
}
}
for
(
=
;
i
<=
;
i
++)
{
if
(
i
]
)
{
return
false
;
}
}
if
(
==
)
{
<
>
=
];
=
fragment
text
.
();
if
(
==
0
)
{
if
(
==
length
)
{
=
=
;
}
else
{
=
=
;
<
>
=
fragment
(
0
,
);
<
>
=
fragment
(
,
length
-
);
.
(
);
.
(
,
leftFragment
);
.
(
+
1
,
rightFragment
);
}
}
else
{
if
(
==
length
)
{
=
+
1
;
=
+
1
;
<
>
=
fragment
(
0
,
);
<
>
=
fragment
(
,
length
-
);
.
(
);
.
(
,
leftFragment
);
.
(
+
1
,
rightFragment
);
}
else
{
=
+
1
;
=
+
1
;
<
>
=
fragment
(
0
,
);
<
>
=
fragment
(
,
-
);
<
>
=
fragment
(
,
length
-
);
.
(
);
.
(
,
leftFragment
);
.
(
+
1
,
middleFragment
);
.
(
+
2
,
rightFragment
);
}
}
}
else
{
<
>
=
];
<
>
=
];
if
(
==
0
)
{
=
;
}
else
{
=
+
1
;
++;
=
fragmentStart
text
.
();
<
>
=
fragmentStart
(
0
,
);
<
>
=
fragmentStart
(
,
length
-
);
.
(
);
.
(
,
leftFragment
);
.
(
+
1
,
rightFragment
);
}
if
(
==
fragmentEnd
text
.
())
{
=
;
}
else
{
=
;
++;
=
fragmentEnd
text
.
();
<
>
=
fragmentStart
(
0
,
);
<
>
=
fragmentEnd
(
,
length
-
);
.
(
);
.
(
,
leftFragment
);
.
(
+
1
,
rightFragment
);
}
}
return
true
;
}
void
::
(
,
,
,
,
::*
,
)
{
for
(
=
;
f
<=
;
f
++)
{
<
>
=
f
];
=
f
==
?
:
0
;
=
f
==
?
:
fragment
text
.
();
fragment
(
start
,
end
-
start
);
fragment
(
start
,
end
-
start
,
,
);
fragment
();
}
}
bool
::
(
,
,
const
&
)
{
,
,
,
,
,
;
(
,
,
fs
,
ss
,
fe
,
se
);
if
(
(
fs
,
ss
,
fe
,
se
,
f1
,
f2
))
{
for
(
=
f1
;
i
<=
f2
;
i
++)
{
i
]
.
;
}
=
false
;
return
true
;
}
else
{
return
false
;
}
}
bool
::
(
,
,
)
{
,
,
,
,
,
;
(
,
,
fs
,
ss
,
fe
,
se
);
if
(
(
fs
,
ss
,
fe
,
se
,
f1
,
f2
))
{
for
(
=
f1
;
i
<=
f2
;
i
++)
{
i
]
.
=
;
}
=
false
;
return
true
;
}
else
{
return
false
;
}
}
bool
::
(
,
,
bool
,
bool
,
bool
,
bool
)
{
,
,
,
,
,
;
(
,
,
fs
,
ss
,
fe
,
se
);
if
(
(
fs
,
ss
,
fe
,
se
,
f1
,
f2
))
{
for
(
=
f1
;
i
<=
f2
;
i
++)
{
i
]
.
=
;
i
]
.
=
;
i
]
.
=
;
i
]
.
=
;
}
=
false
;
return
true
;
}
else
{
return
false
;
}
}
bool
::
(
,
,
)
{
,
,
,
;
(
,
,
fs
,
ss
,
fe
,
se
);
if
(
fs
==-
1
||
ss
==-
1
||
fe
==-
1
||
se
==-
1
)
return
false
;
(
fs
,
ss
,
fe
,
se
, &
::
,
);
return
true
;
}
bool
::
(
,
,
)
{
,
,
,
;
(
,
,
fs
,
ss
,
fe
,
se
);
if
(
fs
==-
1
||
ss
==-
1
||
fe
==-
1
||
se
==-
1
)
return
false
;
(
fs
,
ss
,
fe
,
se
, &
::
,
);
return
true
;
}
bool
::
(
,
,
const
::
&
)
{
,
,
,
,
,
;
(
,
,
fs
,
ss
,
fe
,
se
);
if
(
(
fs
,
ss
,
fe
,
se
,
f1
,
f2
))
{
;
for
(
=
f1
;
i
<=
f2
;
i
++)
{
text
f1
]
;
}
<
>
=
new
(
text
);
for
(
=
f1
;
i
<=
f2
;
i
++)
{
elementFragment
.
(
f1
]);
.
(
f1
);
}
elementFragment
;
.
(
f1
,
elementFragment
);
=
false
;
return
true
;
}
else
{
return
false
;
}
}
::
(
,
)
{
,
,
,
;
(
,
,
fs
,
ss
,
fe
,
se
);
<
>
=
fs
];
if
(
fs
==
fe
&&
ss
==
0
&&
se
==
fragment
text
.
() &&
fragment
)
{
.
(
fs
);
for
(
=
0
;
i
<
fragment
.
();
i
++)
{
.
(
fs
+
i
,
fragment
i
]);
}
=
false
;
return
fragment
;
}
return
();
}
void
::
(
,
&
,
&
)
{
=-
1
;
=-
1
;
if
(!
(
))
return
;
=
0
;
=
.
()-
1
;
while
(
start
<=
end
)
{
=(
start
+
end
)/
2
;
<
>
=
middle
];
=
line
;
=
line
+
line
.
();
if
(
<
lineStart
)
{
if
(
==
lineStart
-
1
)
{
=
middle
-
1
;
=
middle
;
return
;
}
else
{
end
=
middle
-
1
;
}
}
else
if
(
>
lineEnd
)
{
if
(
==
lineEnd
+
1
)
{
=
middle
;
=
middle
+
1
;
return
;
}
else
{
start
=
middle
+
1
;
}
}
else
{
=
middle
;
=
middle
;
return
;
}
}
}
void
::
GetVirtualLineIndexFromTextPos
(
,
,
&
,
&
)
{
=-
1
;
=-
1
;
if
(!
(
))
return
;
if
(
<
0
||
>=
.
())
return
;
<
>
=
];
=
0
;
=
line
.
()-
1
;
while
(
start
<=
end
)
{
=(
start
+
end
)/
2
;
<
>
=
line
middle
];
=
line
+
vline
;
=
line
+
vline
+
vline
;
if
(
<
lineStart
)
{
end
=
middle
-
1
;
}
else
if
(
>
lineEnd
)
{
start
=
middle
+
1
;
}
else
if
(
==
lineStart
)
{
=
middle
==
0
?
0
:
middle
-
1
;
=
middle
;
return
;
}
else
if
(
==
lineEnd
)
{
=
middle
;
=
middle
==
line
.
()-
1
?
middle
:
middle
+
1
;
return
;
}
else
{
=
middle
;
=
middle
;
return
;
}
}
}
void
::
(
,
,
&
,
&
)
{
=-
1
;
=-
1
;
if
(!
(
))
return
;
if
(
<
0
||
>=
.
())
return
;
<
>
=
];
=
0
;
=
line
.
()-
1
;
while
(
start
<=
end
)
{
=(
start
+
end
)/
2
;
<
>
=
line
middle
];
=
line
+
item
;
=
line
+
item
+
item
;
if
(
<
lineStart
)
{
end
=
middle
-
1
;
}
else
if
(
>
lineEnd
)
{
start
=
middle
+
1
;
}
else
if
(
==
lineStart
)
{
=
middle
==
0
?
0
:
middle
-
1
;
=
middle
;
return
;
}
else
if
(
==
lineEnd
)
{
=
middle
;
=
middle
==
line
.
()-
1
?
middle
:
middle
+
1
;
return
;
}
else
{
=
middle
;
=
middle
;
return
;
}
}
}
::
(
,
,
,
bool
)
{
<
>
=
];
if
(
line
<=
&&
<=
line
+
line
.
())
{
if
(
line
==
L""
)
return
line
;
<
>
=
line
];
for
(
=
virtualLine
;
i
<=
virtualLine
;
i
++)
{
<
>
=
line
i
];
if
(
<
>
=
run
.
<
>())
{
=
i
==
virtualLine
?
virtualLine
:
0
;
=
i
==
virtualLine
?
virtualLine
:
run
.
()-
1
;
for
(
=
firstBounds
;
j
<=
lastBounds
;
j
++)
{
::
&
=
run
j
];
=
line
+
run
+
bounds
.
;
if
(
boundsStart
==
)
{
if
(!
||
i
==
virtualLine
&&
j
==
virtualLine
)
{
if
(
run
->
.
.
)
{
return
(
bounds
.
.
,
bounds
.
.
,
bounds
.
.
,
bounds
.
.
);
}
else
{
return
(
bounds
.
.
,
bounds
.
.
,
bounds
.
.
,
bounds
.
.
);
}
}
}
else
if
(
==
boundsStart
+
bounds
.
)
{
if
(
||
i
==
virtualLine
&&
j
==
virtualLine
)
{
if
(
run
->
.
.
)
{
return
(
bounds
.
.
,
bounds
.
.
,
bounds
.
.
,
bounds
.
.
);
}
else
{
return
(
bounds
.
.
,
bounds
.
.
,
bounds
.
.
,
bounds
.
.
);
}
}
}
else
if
(
boundsStart
<
&&
<
boundsStart
+
bounds
.
)
{
=
0
;
=
bounds
.
;
for
(
=
0
;
i
<=
bounds
.
;
i
++)
{
=
bounds
.
+
i
;
=
lastRunChar
;
if
(
i
>
0
)
{
if
(
i
==
bounds
.
)
{
newLastRunChar
=
charIndex
;
}
else
{
=
textRun
.
charIndex
-
1
];
=
textRun
.
charIndex
];
if
(
cluster1
!=
cluster2
)
{
newLastRunChar
=
charIndex
;
}
}
}
if
(
newLastRunChar
!=
lastRunChar
)
{
=
0
;
=
0
;
if
(
run
->
.
.
)
{
glyph2
=
textRun
.
lastRunChar
]+
1
;
glyph1
=
newLastRunChar
==
run
?
0
:
textRun
.
newLastRunChar
]+
1
;
}
else
{
glyph1
=
textRun
.
lastRunChar
];
glyph2
=
newLastRunChar
==
run
?(
)
textRun
.
.
():
textRun
.
newLastRunChar
];
}
=
0
;
for
(
=
glyph1
;
g
<
glyph2
;
g
++)
{
glyphWidth
+=
textRun
.
g
];
}
accumulatedWidth
+=
glyphWidth
;
lastRunChar
=
newLastRunChar
;
if
(
line
+
run
+
lastRunChar
==
)
{
=
0
;
if
(
run
->
.
.
)
{
x
=
bounds
.
.
-
accumulatedWidth
;
}
else
{
x
=
bounds
.
.
+
accumulatedWidth
;
}
return
(
x
,
bounds
.
.
,
x
,
bounds
.
.
);
}
}
}
}
}
}
}
}
return
();
}
::
GetCaretFromXWithTextRunBounds
(
,
,
,
)
{
<
>
=
];
if
(
line
==
L""
)
return
line
;
<
>
=
line
].
<
>();
::
&
=
run
];
=
0
;
=
0
;
while
(
startFromFragmentBounds
<
bounds
.
)
{
=
bounds
.
+
startFromFragmentBounds
;
=
0
;
=
0
;
=
0
;
run
(
charIndex
,
charLength
,
cluster
,
nextCluster
);
=
0
;
=
0
;
if
(
run
->
())
{
clusterStart
=
nextCluster
+
1
;
clusterCount
=
cluster
-
nextCluster
;
}
else
{
clusterStart
=
cluster
;
clusterCount
=
nextCluster
-
cluster
;
}
=
0
;
for
(
=
0
;
i
<
clusterCount
;
i
++)
{
clusterWidth
+=
run
.
i
+
clusterStart
];
}
if
(
run
->
.
.
)
{
=
bounds
.
.
-
accumulatedWidth
;
=
x2
-
clusterWidth
;
if
(
x1
<=
&&
<
x2
)
{
=
-
x1
;
=
x2
-
;
if
(
d1
<=
d2
)
{
return
line
+
run
+
charIndex
+
charLength
;
}
else
{
return
line
+
run
+
charIndex
;
}
}
}
else
{
=
bounds
.
.
+
accumulatedWidth
;
=
x1
+
clusterWidth
;
if
(
x1
<=
&&
<
x2
)
{
=
-
x1
;
=
x2
-
;
if
(
d1
<=
d2
)
{
return
line
+
run
+
charIndex
;
}
else
{
return
line
+
run
+
charIndex
+
charLength
;
}
}
}
startFromFragmentBounds
+=
charLength
;
accumulatedWidth
+=
clusterWidth
;
}
return
-
1
;
}
::
(
,
,
)
{
<
>
=
];
if
(
line
.
()==
0
)
return
line
;
<
>
=
line
];
if
(
<
virtualLine
.
)
return
line
+
virtualLine
;
if
(
>=
virtualLine
.
)
return
line
+
virtualLine
+
virtualLine
;
for
(
=
virtualLine
;
i
<=
virtualLine
;
i
++)
{
<
>
=
line
i
];
if
(
<
>
=
run
.
<
>())
{
=
i
==
virtualLine
?
virtualLine
:
0
;
=
i
==
virtualLine
?
virtualLine
:
run
.
()-
1
;
for
(
=
firstBounds
;
j
<=
lastBounds
;
j
++)
{
::
&
=
run
j
];
if
(
bounds
.
.
<=
&&
<
bounds
.
.
)
{
return
GetCaretFromXWithTextRunBounds
(
,
,
i
,
j
);
}
}
}
else
{
=
run
0
].
;
if
(
bounds
.
<=
&&
<
bounds
.
)
{
=
-
bounds
.
;
=
bounds
.
-
;
if
(
d1
<=
d2
)
{
return
line
+
run
;
}
else
{
return
line
+
run
+
run
;
}
}
}
}
return
-
1
;
}
::
GetInlineObjectFromXWithLine
(
,
,
,
&
,
&
)
{
<
>
=
];
if
(
line
.
()==
0
)
return
();
<
>
=
line
];
if
(
<
virtualLine
.
)
return
();
if
(
>=
virtualLine
.
)
return
();
for
(
=
virtualLine
;
i
<=
virtualLine
;
i
++)
{
<
>
=
line
i
];
if
(
auto
=
run
.
<
UniscribeEmbeddedObjectRun
>())
{
=
run
0
].
;
if
(
bounds
.
<=
&&
<
bounds
.
)
{
=
line
+
elementRun
;
=
elementRun
;
return
elementRun
;
}
}
}
return
();
}
::
(
)
{
if
(
==
.
())
{
return
.
();
}
else
{
return
]
.
;
}
}
::
(
,
)
{
<
>
=
];
if
(
==
line
.
())
{
return
(
+
1
);
}
else
{
return
line
]
.
;
}
}
::
(
)
{
if
(
<
0
]
.
)
return
0
;
if
(
>=
.
()-
1
]
.
)
return
.
()-
1
;
=
0
;
=
.
()-
1
;
while
(
start
<=
end
)
{
=(
start
+
end
)/
2
;
=
(
middle
);
=
(
middle
+
1
);
if
(
<
minY
)
{
end
=
middle
-
1
;
}
else
if
(
>=
maxY
)
{
start
=
middle
+
1
;
}
else
{
return
middle
;
}
}
return
-
1
;
}
::
(
,
)
{
<
>
=
];
if
(
<
line
.
)
return
0
;
if
(
>=
line
.
)
return
line
.
()-
1
;
=
0
;
=
line
.
()-
1
;
while
(
start
<=
end
)
{
=(
start
+
end
)/
2
;
=
(
,
middle
);
=
(
,
middle
+
1
);
if
(
<
minY
)
{
end
=
middle
-
1
;
}
else
if
(
>=
maxY
)
{
start
=
middle
+
1
;
}
else
{
return
middle
;
}
}
return
-
1
;
}
::
(
,
::
,
bool
&
)
{
if
(
==
::
)
return
0
;
if
(
==
::
)
return
.
();
if
(!
(
))
return
-
1
;
if
(
==
::
)
{
return
==
0
?
0
:
GetNearestCaretFromTextPos
(
-
1
,
true
);
}
if
(
==
::
)
{
return
==
.
()?
.
():
GetNearestCaretFromTextPos
(
+
1
,
false
);
}
=
0
;
=
0
;
(
,
frontLine
,
backLine
);
<
>
=
frontLine
];
if
(
line
.
()==
0
)
{
switch
(
)
{
case
::
:
case
::
:
return
line
;
}
}
=
0
;
=
0
;
GetVirtualLineIndexFromTextPos
(
,
frontLine
,
frontVirtualLine
,
backVirtualLine
);
=
?
frontVirtualLine
:
backVirtualLine
;
<
>
=
virtualLineIndex
==-
1
?
nullptr
:
line
virtualLineIndex
];
switch
(
)
{
case
::
:
return
line
+
virtualLine
;
case
::
:
return
line
+
virtualLine
+
virtualLine
;
case
::
:
{
if
(
frontLine
==
0
&&
virtualLineIndex
<=
0
)
return
;
=
(
,
frontLine
,
virtualLineIndex
,
);
if
(
bounds
.
()!=
0
)
{
if
(
virtualLineIndex
<=
0
)
{
frontLine
--;
virtualLineIndex
=
frontLine
]
.
()-
1
;
}
else
{
virtualLineIndex
--;
}
=
true
;
return
(
bounds
.
,
frontLine
,
virtualLineIndex
);
}
}
break
;
case
::
:
{
if
(
frontLine
==
.
()-
1
&&
virtualLineIndex
==
line
.
()-
1
)
return
;
=
(
,
frontLine
,
virtualLineIndex
,
);
if
(
bounds
.
()!=
0
)
{
if
(
virtualLineIndex
==
line
.
()-
1
)
{
frontLine
++;
virtualLineIndex
=
0
;
}
else
{
virtualLineIndex
++;
}
=
false
;
return
(
bounds
.
,
frontLine
,
virtualLineIndex
);
}
}
break
;
}
return
-
1
;
}
::
(
,
bool
)
{
if
(!
(
))
return
();
=
0
;
=
0
;
(
,
frontLine
,
backLine
);
=
0
;
=
0
;
GetVirtualLineIndexFromTextPos
(
,
frontLine
,
frontVirtualLine
,
backVirtualLine
);
=
?
frontVirtualLine
:
backVirtualLine
;
return
(
,
frontLine
,
virtualLineIndex
,
);
}
::
(
)
{
=
(
.
);
if
(
lineIndex
==-
1
)
return
-
1
;
<
>
=
lineIndex
];
if
(
line
.
()==
0
)
return
line
;
=
(
.
,
lineIndex
);
if
(
virtualLineIndex
==-
1
)
return
-
1
;
return
(
.
,
lineIndex
,
virtualLineIndex
);
}
::
(
,
&
,
&
)
{
= -
1
;
=
0
;
=
(
.
);
if
(
lineIndex
== -
1
)
return
();
<
>
=
lineIndex
];
if
(
line
.
() ==
0
)
return
();
=
(
.
,
lineIndex
);
if
(
virtualLineIndex
== -
1
)
return
();
return
GetInlineObjectFromXWithLine
(
.
,
lineIndex
,
virtualLineIndex
,
,
);
}
::
GetNearestCaretFromTextPos
(
,
bool
)
{
if
(!
(
))
return
-
1
;
=
0
;
=
0
;
(
,
frontLine
,
backLine
);
if
(
frontLine
==-
1
||
backLine
==-
1
)
return
-
1
;
if
(
frontLine
!=
backLine
)
{
return
?
-
1
:
+
1
;
}
<
>
=
frontLine
];
if
(
==
line
||
==
line
+
line
.
())
{
return
;
}
=-
1
;
=-
1
;
(
,
frontLine
,
frontItem
,
backItem
);
if
(
frontItem
==-
1
||
backItem
==-
1
)
return
-
1
;
if
(
frontItem
!=
backItem
)
return
;
<
>
=
line
frontItem
];
=
-
line
;
if
(
lineTextPos
==
item
)
return
;
if
(
lineTextPos
==
item
+
item
)
return
;
=
lineTextPos
-
item
;
if
(
item
itemTextPos
].
)
return
;
if
(
)
{
for
(
=
itemTextPos
-
1
;
i
>=
0
;
i
--)
{
if
(
item
i
].
)
return
i
+
line
+
item
;
}
return
line
+
item
;
}
else
{
for
(
=
itemTextPos
+
1
;
i
<
item
;
i
++)
{
if
(
item
i
].
)
return
i
+
line
+
item
;
}
return
line
+
item
+
item
;
}
}
bool
::
(
)
{
if
(!
(
))
return
false
;
return
GetNearestCaretFromTextPos
(
,
true
)==
;
}
bool
::
(
)
{
return
0
<=
&&
<=
.
();
}
}
}
}