Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
7a0a4ce7
Commit
7a0a4ce7
authored
Jan 15, 2014
by
Huw Davies
Committed by
Alexandre Julliard
Jan 15, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
riched20: Add uniscribe support.
parent
57d5b6fc
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
296 additions
and
4 deletions
+296
-4
Makefile.in
dlls/riched20/Makefile.in
+1
-1
editstr.h
dlls/riched20/editstr.h
+12
-0
list.c
dlls/riched20/list.c
+2
-0
paint.c
dlls/riched20/paint.c
+6
-1
run.c
dlls/riched20/run.c
+34
-2
style.c
dlls/riched20/style.c
+2
-0
wrap.c
dlls/riched20/wrap.c
+239
-0
No files found.
dlls/riched20/Makefile.in
View file @
7a0a4ce7
MODULE
=
riched20.dll
IMPORTLIB
=
riched20
IMPORTS
=
uuid ole32 oleaut32 imm32 user32 gdi32
IMPORTS
=
uuid
usp10
ole32 oleaut32 imm32 user32 gdi32
EXTRADLLFLAGS
=
-Wl
,--image-base,0x7ac00000
C_SRCS
=
\
...
...
dlls/riched20/editstr.h
View file @
7a0a4ce7
...
...
@@ -47,6 +47,7 @@
#include <richole.h>
#include "imm.h"
#include <textserv.h>
#include "usp10.h"
#include "wine/debug.h"
#include "wine/list.h"
...
...
@@ -68,6 +69,7 @@ typedef struct tagME_Style
HFONT
hFont
;
/* cached font for the style */
TEXTMETRICW
tm
;
/* cached font metrics for the style */
int
nRefs
;
/* reference count */
SCRIPT_CACHE
script_cache
;
}
ME_Style
;
typedef
enum
{
...
...
@@ -134,6 +136,7 @@ typedef enum {
#define MEPF_CELL 0x04
/* The paragraph is nested in a cell */
#define MEPF_ROWSTART 0x08
/* Hidden empty paragraph at the start of the row */
#define MEPF_ROWEND 0x10
/* Visible empty paragraph at the end of the row */
#define MEPF_COMPLEX 0x20
/* Use uniscribe */
/******************************** structures *************************/
...
...
@@ -150,6 +153,15 @@ typedef struct tagME_Run
int
nAscent
,
nDescent
;
/* pixels above/below baseline */
POINT
pt
;
/* relative to para's position */
REOBJECT
*
ole_obj
;
/* FIXME: should be a union with strText (at least) */
SCRIPT_ANALYSIS
script_analysis
;
int
num_glyphs
,
max_glyphs
;
WORD
*
glyphs
;
SCRIPT_VISATTR
*
vis_attrs
;
int
*
advances
;
GOFFSET
*
offsets
;
int
max_clusters
;
WORD
*
clusters
;
}
ME_Run
;
typedef
struct
tagME_Border
...
...
dlls/riched20/list.c
View file @
7a0a4ce7
...
...
@@ -166,6 +166,8 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item)
if
(
item
->
type
==
diRun
)
{
if
(
item
->
member
.
run
.
ole_obj
)
ME_DeleteReObject
(
item
->
member
.
run
.
ole_obj
);
heap_free
(
item
->
member
.
run
.
glyphs
);
heap_free
(
item
->
member
.
run
.
clusters
);
ME_ReleaseStyle
(
item
->
member
.
run
.
style
);
}
FREE_OBJ
(
item
);
...
...
dlls/riched20/paint.c
View file @
7a0a4ce7
...
...
@@ -331,7 +331,12 @@ static void draw_text( ME_Context *c, ME_Run *run, int x, int y, BOOL selected,
old_text
=
SetTextColor
(
c
->
hDC
,
text_color
);
if
(
selected
)
old_back
=
SetBkColor
(
c
->
hDC
,
back_color
);
ExtTextOutW
(
c
->
hDC
,
x
,
y
,
selected
?
ETO_OPAQUE
:
0
,
sel_rect
,
text
,
run
->
len
,
NULL
);
if
(
run
->
para
->
nFlags
&
MEPF_COMPLEX
)
ScriptTextOut
(
c
->
hDC
,
&
run
->
style
->
script_cache
,
x
,
y
,
selected
?
ETO_OPAQUE
:
0
,
sel_rect
,
&
run
->
script_analysis
,
NULL
,
0
,
run
->
glyphs
,
run
->
num_glyphs
,
run
->
advances
,
NULL
,
run
->
offsets
);
else
ExtTextOutW
(
c
->
hDC
,
x
,
y
,
selected
?
ETO_OPAQUE
:
0
,
sel_rect
,
text
,
run
->
len
,
NULL
);
if
(
selected
)
SetBkColor
(
c
->
hDC
,
old_back
);
SetTextColor
(
c
->
hDC
,
old_text
);
...
...
dlls/riched20/run.c
View file @
7a0a4ce7
...
...
@@ -295,6 +295,14 @@ ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags)
item
->
member
.
run
.
nCharOfs
=
-
1
;
item
->
member
.
run
.
len
=
0
;
item
->
member
.
run
.
para
=
NULL
;
item
->
member
.
run
.
num_glyphs
=
0
;
item
->
member
.
run
.
max_glyphs
=
0
;
item
->
member
.
run
.
glyphs
=
NULL
;
item
->
member
.
run
.
vis_attrs
=
NULL
;
item
->
member
.
run
.
advances
=
NULL
;
item
->
member
.
run
.
offsets
=
NULL
;
item
->
member
.
run
.
max_clusters
=
0
;
item
->
member
.
run
.
clusters
=
NULL
;
ME_AddRefStyle
(
s
);
return
item
;
}
...
...
@@ -468,6 +476,18 @@ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BO
return
1
;
}
if
(
run
->
para
->
nFlags
&
MEPF_COMPLEX
)
{
int
cp
,
trailing
;
if
(
visual_order
&&
run
->
script_analysis
.
fRTL
)
cx
=
run
->
nWidth
-
cx
-
1
;
ScriptXtoCP
(
cx
,
run
->
len
,
run
->
num_glyphs
,
run
->
clusters
,
run
->
vis_attrs
,
run
->
advances
,
&
run
->
script_analysis
,
&
cp
,
&
trailing
);
TRACE
(
"x %d cp %d trailing %d (run width %d) rtl %d log order %d
\n
"
,
cx
,
cp
,
trailing
,
run
->
nWidth
,
run
->
script_analysis
.
fRTL
,
run
->
script_analysis
.
fLogicalOrder
);
return
closest
?
cp
+
trailing
:
cp
;
}
if
(
c
->
editor
->
cPasswordMask
)
{
mask_text
=
ME_MakeStringR
(
c
->
editor
->
cPasswordMask
,
run
->
len
);
...
...
@@ -543,6 +563,14 @@ int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visua
nOffset
=
0
;
}
if
(
pRun
->
para
->
nFlags
&
MEPF_COMPLEX
)
{
int
x
;
ScriptCPtoX
(
nOffset
,
FALSE
,
pRun
->
len
,
pRun
->
num_glyphs
,
pRun
->
clusters
,
pRun
->
vis_attrs
,
pRun
->
advances
,
&
pRun
->
script_analysis
,
&
x
);
if
(
visual_order
&&
pRun
->
script_analysis
.
fRTL
)
x
=
pRun
->
nWidth
-
x
-
1
;
return
x
;
}
if
(
c
->
editor
->
cPasswordMask
)
{
mask_text
=
ME_MakeStringR
(
c
->
editor
->
cPasswordMask
,
pRun
->
len
);
...
...
@@ -592,8 +620,12 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, i
* this is wasteful for MERF_NONTEXT runs, but that shouldn't matter
* in practice
*/
if
(
c
->
editor
->
cPasswordMask
)
if
(
para
->
nFlags
&
MEPF_COMPLEX
)
{
size
.
cx
=
run
->
nWidth
;
}
else
if
(
c
->
editor
->
cPasswordMask
)
{
ME_String
*
szMasked
=
ME_MakeStringR
(
c
->
editor
->
cPasswordMask
,
nLen
);
ME_GetTextExtent
(
c
,
szMasked
->
szData
,
nLen
,
run
->
style
,
&
size
);
...
...
dlls/riched20/style.c
View file @
7a0a4ce7
...
...
@@ -149,6 +149,7 @@ ME_Style *ME_MakeStyle(CHARFORMAT2W *style)
s
->
hFont
=
NULL
;
memset
(
&
s
->
tm
,
0
,
sizeof
(
s
->
tm
));
s
->
tm
.
tmAscent
=
-
1
;
s
->
script_cache
=
NULL
;
all_refs
++
;
TRACE_
(
richedit_style
)(
"ME_MakeStyle %p, total refs=%d
\n
"
,
s
,
all_refs
);
return
s
;
...
...
@@ -435,6 +436,7 @@ static void ME_DestroyStyle(ME_Style *s) {
DeleteObject
(
s
->
hFont
);
s
->
hFont
=
NULL
;
}
ScriptFreeCache
(
&
s
->
script_cache
);
FREE_OBJ
(
s
);
}
...
...
dlls/riched20/wrap.c
View file @
7a0a4ce7
...
...
@@ -32,6 +32,66 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
* - no tabs
*/
static
BOOL
get_run_glyph_buffers
(
ME_Run
*
run
)
{
heap_free
(
run
->
glyphs
);
run
->
glyphs
=
heap_alloc
(
run
->
max_glyphs
*
(
sizeof
(
WORD
)
+
sizeof
(
SCRIPT_VISATTR
)
+
sizeof
(
int
)
+
sizeof
(
GOFFSET
))
);
if
(
!
run
->
glyphs
)
return
FALSE
;
run
->
vis_attrs
=
(
SCRIPT_VISATTR
*
)((
char
*
)
run
->
glyphs
+
run
->
max_glyphs
*
sizeof
(
WORD
));
run
->
advances
=
(
int
*
)((
char
*
)
run
->
glyphs
+
run
->
max_glyphs
*
(
sizeof
(
WORD
)
+
sizeof
(
SCRIPT_VISATTR
)));
run
->
offsets
=
(
GOFFSET
*
)((
char
*
)
run
->
glyphs
+
run
->
max_glyphs
*
(
sizeof
(
WORD
)
+
sizeof
(
SCRIPT_VISATTR
)
+
sizeof
(
int
)));
return
TRUE
;
}
static
HRESULT
shape_run
(
ME_Context
*
c
,
ME_Run
*
run
)
{
HRESULT
hr
;
HFONT
old_font
;
int
i
;
if
(
!
run
->
glyphs
)
{
run
->
max_glyphs
=
1
.
5
*
run
->
len
+
16
;
/* This is suggested in the uniscribe documentation */
run
->
max_glyphs
=
(
run
->
max_glyphs
+
7
)
&
~
7
;
/* Keep alignment simple */
get_run_glyph_buffers
(
run
);
}
if
(
run
->
max_clusters
<
run
->
len
)
{
heap_free
(
run
->
clusters
);
run
->
max_clusters
=
run
->
len
*
2
;
run
->
clusters
=
heap_alloc
(
run
->
max_clusters
*
sizeof
(
WORD
)
);
}
old_font
=
ME_SelectStyleFont
(
c
,
run
->
style
);
while
(
1
)
{
hr
=
ScriptShape
(
c
->
hDC
,
&
run
->
style
->
script_cache
,
get_text
(
run
,
0
),
run
->
len
,
run
->
max_glyphs
,
&
run
->
script_analysis
,
run
->
glyphs
,
run
->
clusters
,
run
->
vis_attrs
,
&
run
->
num_glyphs
);
if
(
hr
!=
E_OUTOFMEMORY
)
break
;
if
(
run
->
max_glyphs
>
10
*
run
->
len
)
break
;
/* something has clearly gone wrong */
run
->
max_glyphs
*=
2
;
get_run_glyph_buffers
(
run
);
}
if
(
SUCCEEDED
(
hr
))
hr
=
ScriptPlace
(
c
->
hDC
,
&
run
->
style
->
script_cache
,
run
->
glyphs
,
run
->
num_glyphs
,
run
->
vis_attrs
,
&
run
->
script_analysis
,
run
->
advances
,
run
->
offsets
,
NULL
);
if
(
SUCCEEDED
(
hr
))
{
for
(
i
=
0
,
run
->
nWidth
=
0
;
i
<
run
->
num_glyphs
;
i
++
)
run
->
nWidth
+=
run
->
advances
[
i
];
}
ME_UnselectStyleFont
(
c
,
run
->
style
,
old_font
);
return
hr
;
}
/******************************************************************************
* calc_run_extent
*
...
...
@@ -78,7 +138,10 @@ static ME_DisplayItem *split_run_extents(ME_WrapContext *wc, ME_DisplayItem *ite
ME_SplitRunSimple
(
editor
,
&
cursor
);
run2
=
&
cursor
.
pRun
->
member
.
run
;
run2
->
script_analysis
=
run
->
script_analysis
;
shape_run
(
wc
->
context
,
run
);
shape_run
(
wc
->
context
,
run2
);
calc_run_extent
(
wc
->
context
,
para
,
wc
->
nRow
?
wc
->
nLeftMargin
:
wc
->
nFirstMargin
,
run
);
run2
->
pt
.
x
=
run
->
pt
.
x
+
run
->
nWidth
;
...
...
@@ -166,6 +229,65 @@ static void ME_BeginRow(ME_WrapContext *wc)
wc
->
pt
.
y
++
;
}
static
void
layout_row
(
ME_DisplayItem
*
start
,
const
ME_DisplayItem
*
end
)
{
ME_DisplayItem
*
p
;
int
i
,
num_runs
=
0
;
int
buf
[
16
*
5
];
/* 5 arrays - 4 of int & 1 of BYTE, alloc space for 5 of ints */
int
*
vis_to_log
=
buf
,
*
log_to_vis
,
*
widths
,
*
pos
;
BYTE
*
levels
;
BOOL
found_black
=
FALSE
;
for
(
p
=
end
->
prev
;
p
!=
start
->
prev
;
p
=
p
->
prev
)
{
if
(
p
->
type
==
diRun
)
{
if
(
!
found_black
)
found_black
=
!
(
p
->
member
.
run
.
nFlags
&
(
MERF_WHITESPACE
|
MERF_ENDPARA
));
if
(
found_black
)
num_runs
++
;
}
}
TRACE
(
"%d runs
\n
"
,
num_runs
);
if
(
!
num_runs
)
return
;
if
(
num_runs
>
sizeof
(
buf
)
/
(
sizeof
(
buf
[
0
])
*
5
))
vis_to_log
=
heap_alloc
(
num_runs
*
sizeof
(
int
)
*
5
);
log_to_vis
=
vis_to_log
+
num_runs
;
widths
=
vis_to_log
+
2
*
num_runs
;
pos
=
vis_to_log
+
3
*
num_runs
;
levels
=
(
BYTE
*
)(
vis_to_log
+
4
*
num_runs
);
for
(
i
=
0
,
p
=
start
;
i
<
num_runs
;
p
=
p
->
next
)
{
if
(
p
->
type
==
diRun
)
{
levels
[
i
]
=
p
->
member
.
run
.
script_analysis
.
s
.
uBidiLevel
;
widths
[
i
]
=
p
->
member
.
run
.
nWidth
;
TRACE
(
"%d: level %d width %d
\n
"
,
i
,
levels
[
i
],
widths
[
i
]
);
i
++
;
}
}
ScriptLayout
(
num_runs
,
levels
,
vis_to_log
,
log_to_vis
);
pos
[
0
]
=
start
->
member
.
run
.
para
->
pt
.
x
;
for
(
i
=
1
;
i
<
num_runs
;
i
++
)
pos
[
i
]
=
pos
[
i
-
1
]
+
widths
[
vis_to_log
[
i
-
1
]
];
for
(
i
=
0
,
p
=
start
;
i
<
num_runs
;
p
=
p
->
next
)
{
if
(
p
->
type
==
diRun
)
{
p
->
member
.
run
.
pt
.
x
=
pos
[
log_to_vis
[
i
]
];
TRACE
(
"%d: x = %d
\n
"
,
i
,
p
->
member
.
run
.
pt
.
x
);
i
++
;
}
}
if
(
vis_to_log
!=
buf
)
heap_free
(
vis_to_log
);
}
static
void
ME_InsertRowStart
(
ME_WrapContext
*
wc
,
const
ME_DisplayItem
*
pEnd
)
{
ME_DisplayItem
*
p
,
*
row
;
...
...
@@ -227,6 +349,9 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
shift
=
max
((
wc
->
nAvailWidth
-
width
)
/
2
,
0
);
if
(
align
==
PFA_RIGHT
)
shift
=
max
(
wc
->
nAvailWidth
-
width
,
0
);
if
(
para
->
nFlags
&
MEPF_COMPLEX
)
layout_row
(
wc
->
pRowStart
,
pEnd
);
row
->
member
.
row
.
pt
.
x
=
row
->
member
.
row
.
nLMargin
+
shift
;
for
(
p
=
wc
->
pRowStart
;
p
!=
pEnd
;
p
=
p
->
next
)
{
...
...
@@ -613,6 +738,111 @@ static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) {
}
}
static
HRESULT
itemize_para
(
ME_Context
*
c
,
ME_DisplayItem
*
p
)
{
ME_Paragraph
*
para
=
&
p
->
member
.
para
;
ME_Run
*
run
;
ME_DisplayItem
*
di
;
SCRIPT_ITEM
buf
[
16
],
*
items
=
buf
;
int
items_passed
=
sizeof
(
buf
)
/
sizeof
(
buf
[
0
]
),
num_items
,
cur_item
;
SCRIPT_CONTROL
control
=
{
LANG_USER_DEFAULT
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
0
};
SCRIPT_STATE
state
=
{
0
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
0
,
0
};
HRESULT
hr
;
assert
(
p
->
type
==
diParagraph
);
while
(
1
)
{
hr
=
ScriptItemize
(
para
->
text
->
szData
,
para
->
text
->
nLen
,
items_passed
,
&
control
,
&
state
,
items
,
&
num_items
);
if
(
hr
!=
E_OUTOFMEMORY
)
break
;
/* may not be enough items if hr == E_OUTOFMEMORY */
if
(
items_passed
>
para
->
text
->
nLen
+
1
)
break
;
/* something else has gone wrong */
items_passed
*=
2
;
if
(
items
==
buf
)
items
=
heap_alloc
(
items_passed
*
sizeof
(
*
items
)
);
else
items
=
heap_realloc
(
items
,
items_passed
*
sizeof
(
*
items
)
);
if
(
!
items
)
break
;
}
if
(
FAILED
(
hr
))
goto
end
;
if
(
TRACE_ON
(
richedit
))
{
TRACE
(
"got items:
\n
"
);
for
(
cur_item
=
0
;
cur_item
<
num_items
;
cur_item
++
)
{
TRACE
(
"
\t
%d - %d RTL %d bidi level %d
\n
"
,
items
[
cur_item
].
iCharPos
,
items
[
cur_item
+
1
].
iCharPos
-
1
,
items
[
cur_item
].
a
.
fRTL
,
items
[
cur_item
].
a
.
s
.
uBidiLevel
);
}
TRACE
(
"before splitting runs into ranges
\n
"
);
for
(
di
=
p
->
next
;
di
!=
p
->
member
.
para
.
next_para
;
di
=
di
->
next
)
{
if
(
di
->
type
!=
diRun
)
continue
;
TRACE
(
"
\t
%d: %s
\n
"
,
di
->
member
.
run
.
nCharOfs
,
debugstr_run
(
&
di
->
member
.
run
)
);
}
}
/* split runs into ranges at item boundaries */
for
(
di
=
p
->
next
,
cur_item
=
0
;
di
!=
p
->
member
.
para
.
next_para
;
di
=
di
->
next
)
{
if
(
di
->
type
!=
diRun
)
continue
;
run
=
&
di
->
member
.
run
;
if
(
run
->
nCharOfs
==
items
[
cur_item
+
1
].
iCharPos
)
cur_item
++
;
items
[
cur_item
].
a
.
fLogicalOrder
=
TRUE
;
run
->
script_analysis
=
items
[
cur_item
].
a
;
if
(
run
->
nFlags
&
MERF_ENDPARA
)
break
;
/* don't split eop runs */
if
(
run
->
nCharOfs
+
run
->
len
>
items
[
cur_item
+
1
].
iCharPos
)
{
ME_Cursor
cursor
=
{
p
,
di
,
items
[
cur_item
+
1
].
iCharPos
-
run
->
nCharOfs
};
ME_SplitRunSimple
(
c
->
editor
,
&
cursor
);
}
}
if
(
TRACE_ON
(
richedit
))
{
TRACE
(
"after splitting into ranges
\n
"
);
for
(
di
=
p
->
next
;
di
!=
p
->
member
.
para
.
next_para
;
di
=
di
->
next
)
{
if
(
di
->
type
!=
diRun
)
continue
;
TRACE
(
"
\t
%d: %s
\n
"
,
di
->
member
.
run
.
nCharOfs
,
debugstr_run
(
&
di
->
member
.
run
)
);
}
}
para
->
nFlags
|=
MEPF_COMPLEX
;
end:
if
(
items
!=
buf
)
heap_free
(
items
);
return
hr
;
}
static
HRESULT
shape_para
(
ME_Context
*
c
,
ME_DisplayItem
*
p
)
{
ME_DisplayItem
*
di
;
ME_Run
*
run
;
HRESULT
hr
;
for
(
di
=
p
->
next
;
di
!=
p
->
member
.
para
.
next_para
;
di
=
di
->
next
)
{
if
(
di
->
type
!=
diRun
)
continue
;
run
=
&
di
->
member
.
run
;
hr
=
shape_run
(
c
,
run
);
if
(
FAILED
(
hr
))
{
run
->
para
->
nFlags
&=
~
MEPF_COMPLEX
;
return
hr
;
}
}
return
hr
;
}
static
void
ME_WrapTextParagraph
(
ME_Context
*
c
,
ME_DisplayItem
*
tp
)
{
ME_DisplayItem
*
p
;
ME_WrapContext
wc
;
...
...
@@ -625,6 +855,15 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
return
;
}
ME_PrepareParagraphForWrapping
(
c
,
tp
);
/* For now treating all non-password text as complex for better testing */
if
(
!
c
->
editor
->
cPasswordMask
/* &&
ScriptIsComplex( tp->member.para.text->szData, tp->member.para.text->nLen, SIC_COMPLEX ) == S_OK */
)
{
if
(
SUCCEEDED
(
itemize_para
(
c
,
tp
)
))
shape_para
(
c
,
tp
);
}
pFmt
=
tp
->
member
.
para
.
pFmt
;
wc
.
context
=
c
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment