Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
65f80924
Commit
65f80924
authored
Dec 20, 2011
by
Kusanagi Kouichi
Committed by
Alexandre Julliard
Dec 20, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gdi32: Split AddFontToList into two functions.
parent
4dfe084b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
211 additions
and
197 deletions
+211
-197
freetype.c
dlls/gdi32/freetype.c
+211
-197
No files found.
dlls/gdi32/freetype.c
View file @
65f80924
...
...
@@ -1454,20 +1454,223 @@ static void AddFaceToFamily(Face *face, Family *family)
#define ADDFONT_FORCE_BITMAP 0x02
#define ADDFONT_ADD_TO_CACHE 0x04
static
void
AddFaceToList
(
FT_Face
ft_face
,
char
*
fake_family
,
const
char
*
file
,
void
*
font_data_ptr
,
DWORD
font_data_size
,
FT_Long
face_index
,
DWORD
flags
)
{
int
bitmap_num
=
0
;
Family
*
family
;
WCHAR
*
StyleW
;
do
{
TT_OS2
*
pOS2
;
TT_Header
*
pHeader
;
WCHAR
*
english_family
,
*
localised_family
;
Face
*
face
;
struct
list
*
face_elem_ptr
;
FT_WinFNT_HeaderRec
winfnt_header
;
int
internal_leading
;
FONTSIGNATURE
fs
;
My_FT_Bitmap_Size
*
size
=
NULL
;
FT_ULong
tmp_size
;
if
(
!
FT_IS_SCALABLE
(
ft_face
))
size
=
(
My_FT_Bitmap_Size
*
)
ft_face
->
available_sizes
+
bitmap_num
;
if
(
fake_family
)
{
english_family
=
towstr
(
CP_ACP
,
fake_family
);
localised_family
=
NULL
;
}
else
{
english_family
=
get_face_name
(
ft_face
,
TT_NAME_ID_FONT_FAMILY
,
TT_MS_LANGID_ENGLISH_UNITED_STATES
);
if
(
!
english_family
)
english_family
=
towstr
(
CP_ACP
,
ft_face
->
family_name
);
localised_family
=
get_face_name
(
ft_face
,
TT_NAME_ID_FONT_FAMILY
,
GetUserDefaultLCID
());
if
(
localised_family
&&
!
strcmpiW
(
localised_family
,
english_family
))
{
HeapFree
(
GetProcessHeap
(),
0
,
localised_family
);
localised_family
=
NULL
;
}
}
family
=
find_family_from_name
(
localised_family
?
localised_family
:
english_family
);
if
(
!
family
)
{
family
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
family
));
family
->
FamilyName
=
strdupW
(
localised_family
?
localised_family
:
english_family
);
family
->
EnglishName
=
localised_family
?
strdupW
(
english_family
)
:
NULL
;
list_init
(
&
family
->
faces
);
list_add_tail
(
&
font_list
,
&
family
->
entry
);
if
(
localised_family
)
{
FontSubst
*
subst
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
subst
));
subst
->
from
.
name
=
strdupW
(
english_family
);
subst
->
from
.
charset
=
-
1
;
subst
->
to
.
name
=
strdupW
(
localised_family
);
subst
->
to
.
charset
=
-
1
;
add_font_subst
(
&
font_subst_list
,
subst
,
0
);
}
}
HeapFree
(
GetProcessHeap
(),
0
,
localised_family
);
HeapFree
(
GetProcessHeap
(),
0
,
english_family
);
StyleW
=
towstr
(
CP_ACP
,
ft_face
->
style_name
);
internal_leading
=
0
;
memset
(
&
fs
,
0
,
sizeof
(
fs
));
pOS2
=
pFT_Get_Sfnt_Table
(
ft_face
,
ft_sfnt_os2
);
if
(
pOS2
)
{
fs
.
fsCsb
[
0
]
=
pOS2
->
ulCodePageRange1
;
fs
.
fsCsb
[
1
]
=
pOS2
->
ulCodePageRange2
;
fs
.
fsUsb
[
0
]
=
pOS2
->
ulUnicodeRange1
;
fs
.
fsUsb
[
1
]
=
pOS2
->
ulUnicodeRange2
;
fs
.
fsUsb
[
2
]
=
pOS2
->
ulUnicodeRange3
;
fs
.
fsUsb
[
3
]
=
pOS2
->
ulUnicodeRange4
;
if
(
pOS2
->
version
==
0
)
{
FT_UInt
dummy
;
if
(
pFT_Get_First_Char
(
ft_face
,
&
dummy
)
<
0x100
)
fs
.
fsCsb
[
0
]
|=
FS_LATIN1
;
else
fs
.
fsCsb
[
0
]
|=
FS_SYMBOL
;
}
}
else
if
(
!
pFT_Get_WinFNT_Header
(
ft_face
,
&
winfnt_header
))
{
CHARSETINFO
csi
;
TRACE
(
"pix_h %d charset %d dpi %dx%d pt %d
\n
"
,
winfnt_header
.
pixel_height
,
winfnt_header
.
charset
,
winfnt_header
.
vertical_resolution
,
winfnt_header
.
horizontal_resolution
,
winfnt_header
.
nominal_point_size
);
if
(
TranslateCharsetInfo
((
DWORD
*
)(
UINT_PTR
)
winfnt_header
.
charset
,
&
csi
,
TCI_SRCCHARSET
))
fs
=
csi
.
fs
;
internal_leading
=
winfnt_header
.
internal_leading
;
}
pHeader
=
pFT_Get_Sfnt_Table
(
ft_face
,
ft_sfnt_head
);
LIST_FOR_EACH
(
face_elem_ptr
,
&
family
->
faces
)
{
face
=
LIST_ENTRY
(
face_elem_ptr
,
Face
,
entry
);
if
(
!
strcmpiW
(
face
->
StyleName
,
StyleW
)
&&
(
FT_IS_SCALABLE
(
ft_face
)
||
((
size
->
y_ppem
==
face
->
size
.
y_ppem
)
&&
!
memcmp
(
&
fs
,
&
face
->
fs
,
sizeof
(
fs
))
)))
{
TRACE
(
"Already loaded font %s %s original version is %lx, this version is %lx
\n
"
,
debugstr_w
(
family
->
FamilyName
),
debugstr_w
(
StyleW
),
face
->
font_version
,
pHeader
?
pHeader
->
Font_Revision
:
0
);
if
(
fake_family
)
{
TRACE
(
"This font is a replacement but the original really exists, so we'll skip the replacement
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
StyleW
);
return
;
}
if
(
!
pHeader
||
pHeader
->
Font_Revision
<=
face
->
font_version
)
{
TRACE
(
"Original font is newer so skipping this one
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
StyleW
);
return
;
}
else
{
TRACE
(
"Replacing original with this one
\n
"
);
list_remove
(
&
face
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
face
->
file
);
HeapFree
(
GetProcessHeap
(),
0
,
face
->
StyleName
);
HeapFree
(
GetProcessHeap
(),
0
,
face
->
FullName
);
HeapFree
(
GetProcessHeap
(),
0
,
face
);
break
;
}
}
}
face
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
face
));
face
->
cached_enum_data
=
NULL
;
face
->
StyleName
=
StyleW
;
face
->
FullName
=
get_face_name
(
ft_face
,
TT_NAME_ID_FULL_NAME
,
TT_MS_LANGID_ENGLISH_UNITED_STATES
);
if
(
file
)
{
face
->
file
=
strdupA
(
file
);
face
->
font_data_ptr
=
NULL
;
face
->
font_data_size
=
0
;
}
else
{
face
->
file
=
NULL
;
face
->
font_data_ptr
=
font_data_ptr
;
face
->
font_data_size
=
font_data_size
;
}
face
->
face_index
=
face_index
;
face
->
ntmFlags
=
0
;
if
(
ft_face
->
style_flags
&
FT_STYLE_FLAG_ITALIC
)
face
->
ntmFlags
|=
NTM_ITALIC
;
if
(
ft_face
->
style_flags
&
FT_STYLE_FLAG_BOLD
)
face
->
ntmFlags
|=
NTM_BOLD
;
if
(
face
->
ntmFlags
==
0
)
face
->
ntmFlags
=
NTM_REGULAR
;
face
->
font_version
=
pHeader
?
pHeader
->
Font_Revision
:
0
;
face
->
family
=
family
;
face
->
external
=
(
flags
&
ADDFONT_EXTERNAL_FONT
)
?
TRUE
:
FALSE
;
face
->
fs
=
fs
;
memset
(
&
face
->
fs_links
,
0
,
sizeof
(
face
->
fs_links
));
if
(
FT_IS_SCALABLE
(
ft_face
))
{
memset
(
&
face
->
size
,
0
,
sizeof
(
face
->
size
));
face
->
scalable
=
TRUE
;
}
else
{
TRACE
(
"Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld
\n
"
,
size
->
height
,
size
->
width
,
size
->
size
>>
6
,
size
->
x_ppem
>>
6
,
size
->
y_ppem
>>
6
);
face
->
size
.
height
=
size
->
height
;
face
->
size
.
width
=
size
->
width
;
face
->
size
.
size
=
size
->
size
;
face
->
size
.
x_ppem
=
size
->
x_ppem
;
face
->
size
.
y_ppem
=
size
->
y_ppem
;
face
->
size
.
internal_leading
=
internal_leading
;
face
->
scalable
=
FALSE
;
}
/* check for the presence of the 'CFF ' table to check if the font is Type1 */
tmp_size
=
0
;
if
(
!
pFT_Load_Sfnt_Table
(
ft_face
,
FT_MAKE_TAG
(
'C'
,
'F'
,
'F'
,
' '
),
0
,
NULL
,
&
tmp_size
))
{
TRACE
(
"Font %s/%p is OTF Type1
\n
"
,
wine_dbgstr_a
(
file
),
font_data_ptr
);
face
->
ntmFlags
|=
NTM_PS_OPENTYPE
;
}
TRACE
(
"fsCsb = %08x %08x/%08x %08x %08x %08x
\n
"
,
face
->
fs
.
fsCsb
[
0
],
face
->
fs
.
fsCsb
[
1
],
face
->
fs
.
fsUsb
[
0
],
face
->
fs
.
fsUsb
[
1
],
face
->
fs
.
fsUsb
[
2
],
face
->
fs
.
fsUsb
[
3
]);
if
(
face
->
fs
.
fsCsb
[
0
]
==
0
)
{
int
i
;
/* let's see if we can find any interesting cmaps */
for
(
i
=
0
;
i
<
ft_face
->
num_charmaps
;
i
++
)
{
switch
(
ft_face
->
charmaps
[
i
]
->
encoding
)
{
case
FT_ENCODING_UNICODE
:
case
FT_ENCODING_APPLE_ROMAN
:
face
->
fs
.
fsCsb
[
0
]
|=
FS_LATIN1
;
break
;
case
FT_ENCODING_MS_SYMBOL
:
face
->
fs
.
fsCsb
[
0
]
|=
FS_SYMBOL
;
break
;
default:
break
;
}
}
}
if
(
flags
&
ADDFONT_ADD_TO_CACHE
)
add_face_to_cache
(
face
);
AddFaceToFamily
(
face
,
family
);
}
while
(
!
FT_IS_SCALABLE
(
ft_face
)
&&
++
bitmap_num
<
ft_face
->
num_fixed_sizes
);
TRACE
(
"Added font %s %s
\n
"
,
debugstr_w
(
family
->
FamilyName
),
debugstr_w
(
StyleW
));
}
static
INT
AddFontToList
(
const
char
*
file
,
void
*
font_data_ptr
,
DWORD
font_data_size
,
char
*
fake_family
,
const
WCHAR
*
target_family
,
DWORD
flags
)
{
FT_Face
ft_face
;
TT_OS2
*
pOS2
;
TT_Header
*
pHeader
=
NULL
;
WCHAR
*
english_family
,
*
localised_family
,
*
StyleW
;
Family
*
family
;
Face
*
face
;
struct
list
*
face_elem_ptr
;
WCHAR
*
localised_family
;
FT_Error
err
;
FT_Long
face_index
=
0
,
num_faces
;
FT_WinFNT_HeaderRec
winfnt_header
;
int
i
,
bitmap_num
,
internal_leading
;
FONTSIGNATURE
fs
;
/* we always load external fonts from files - otherwise we would get a crash in update_reg_entries */
assert
(
file
||
!
(
flags
&
ADDFONT_EXTERNAL_FONT
));
...
...
@@ -1576,199 +1779,10 @@ static INT AddFontToList(const char *file, void *font_data_ptr, DWORD font_data_
HeapFree
(
GetProcessHeap
(),
0
,
localised_family
);
}
bitmap_num
=
0
;
do
{
My_FT_Bitmap_Size
*
size
=
NULL
;
FT_ULong
tmp_size
;
if
(
!
FT_IS_SCALABLE
(
ft_face
))
size
=
(
My_FT_Bitmap_Size
*
)
ft_face
->
available_sizes
+
bitmap_num
;
if
(
fake_family
)
{
english_family
=
towstr
(
CP_ACP
,
fake_family
);
localised_family
=
NULL
;
}
else
{
english_family
=
get_face_name
(
ft_face
,
TT_NAME_ID_FONT_FAMILY
,
TT_MS_LANGID_ENGLISH_UNITED_STATES
);
if
(
!
english_family
)
english_family
=
towstr
(
CP_ACP
,
ft_face
->
family_name
);
localised_family
=
get_face_name
(
ft_face
,
TT_NAME_ID_FONT_FAMILY
,
GetUserDefaultLCID
());
if
(
localised_family
&&
!
strcmpiW
(
localised_family
,
english_family
))
{
HeapFree
(
GetProcessHeap
(),
0
,
localised_family
);
localised_family
=
NULL
;
}
}
family
=
find_family_from_name
(
localised_family
?
localised_family
:
english_family
);
if
(
!
family
)
{
family
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
family
));
family
->
FamilyName
=
strdupW
(
localised_family
?
localised_family
:
english_family
);
family
->
EnglishName
=
localised_family
?
strdupW
(
english_family
)
:
NULL
;
list_init
(
&
family
->
faces
);
list_add_tail
(
&
font_list
,
&
family
->
entry
);
if
(
localised_family
)
{
FontSubst
*
subst
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
subst
));
subst
->
from
.
name
=
strdupW
(
english_family
);
subst
->
from
.
charset
=
-
1
;
subst
->
to
.
name
=
strdupW
(
localised_family
);
subst
->
to
.
charset
=
-
1
;
add_font_subst
(
&
font_subst_list
,
subst
,
0
);
}
}
HeapFree
(
GetProcessHeap
(),
0
,
localised_family
);
HeapFree
(
GetProcessHeap
(),
0
,
english_family
);
StyleW
=
towstr
(
CP_ACP
,
ft_face
->
style_name
);
internal_leading
=
0
;
memset
(
&
fs
,
0
,
sizeof
(
fs
));
pOS2
=
pFT_Get_Sfnt_Table
(
ft_face
,
ft_sfnt_os2
);
if
(
pOS2
)
{
fs
.
fsCsb
[
0
]
=
pOS2
->
ulCodePageRange1
;
fs
.
fsCsb
[
1
]
=
pOS2
->
ulCodePageRange2
;
fs
.
fsUsb
[
0
]
=
pOS2
->
ulUnicodeRange1
;
fs
.
fsUsb
[
1
]
=
pOS2
->
ulUnicodeRange2
;
fs
.
fsUsb
[
2
]
=
pOS2
->
ulUnicodeRange3
;
fs
.
fsUsb
[
3
]
=
pOS2
->
ulUnicodeRange4
;
if
(
pOS2
->
version
==
0
)
{
FT_UInt
dummy
;
if
(
pFT_Get_First_Char
(
ft_face
,
&
dummy
)
<
0x100
)
fs
.
fsCsb
[
0
]
|=
FS_LATIN1
;
else
fs
.
fsCsb
[
0
]
|=
FS_SYMBOL
;
}
}
else
if
(
!
pFT_Get_WinFNT_Header
(
ft_face
,
&
winfnt_header
))
{
CHARSETINFO
csi
;
TRACE
(
"pix_h %d charset %d dpi %dx%d pt %d
\n
"
,
winfnt_header
.
pixel_height
,
winfnt_header
.
charset
,
winfnt_header
.
vertical_resolution
,
winfnt_header
.
horizontal_resolution
,
winfnt_header
.
nominal_point_size
);
if
(
TranslateCharsetInfo
((
DWORD
*
)(
UINT_PTR
)
winfnt_header
.
charset
,
&
csi
,
TCI_SRCCHARSET
))
fs
=
csi
.
fs
;
internal_leading
=
winfnt_header
.
internal_leading
;
}
LIST_FOR_EACH
(
face_elem_ptr
,
&
family
->
faces
)
{
face
=
LIST_ENTRY
(
face_elem_ptr
,
Face
,
entry
);
if
(
!
strcmpiW
(
face
->
StyleName
,
StyleW
)
&&
(
FT_IS_SCALABLE
(
ft_face
)
||
((
size
->
y_ppem
==
face
->
size
.
y_ppem
)
&&
!
memcmp
(
&
fs
,
&
face
->
fs
,
sizeof
(
fs
))
)))
{
TRACE
(
"Already loaded font %s %s original version is %lx, this version is %lx
\n
"
,
debugstr_w
(
family
->
FamilyName
),
debugstr_w
(
StyleW
),
face
->
font_version
,
pHeader
?
pHeader
->
Font_Revision
:
0
);
if
(
fake_family
)
{
TRACE
(
"This font is a replacement but the original really exists, so we'll skip the replacement
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
StyleW
);
pFT_Done_Face
(
ft_face
);
return
1
;
}
if
(
!
pHeader
||
pHeader
->
Font_Revision
<=
face
->
font_version
)
{
TRACE
(
"Original font is newer so skipping this one
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
StyleW
);
pFT_Done_Face
(
ft_face
);
return
1
;
}
else
{
TRACE
(
"Replacing original with this one
\n
"
);
list_remove
(
&
face
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
face
->
file
);
HeapFree
(
GetProcessHeap
(),
0
,
face
->
StyleName
);
HeapFree
(
GetProcessHeap
(),
0
,
face
->
FullName
);
HeapFree
(
GetProcessHeap
(),
0
,
face
);
break
;
}
}
}
face
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
face
));
face
->
cached_enum_data
=
NULL
;
face
->
StyleName
=
StyleW
;
face
->
FullName
=
get_face_name
(
ft_face
,
TT_NAME_ID_FULL_NAME
,
TT_MS_LANGID_ENGLISH_UNITED_STATES
);
if
(
file
)
{
face
->
file
=
strdupA
(
file
);
face
->
font_data_ptr
=
NULL
;
face
->
font_data_size
=
0
;
}
else
{
face
->
file
=
NULL
;
face
->
font_data_ptr
=
font_data_ptr
;
face
->
font_data_size
=
font_data_size
;
}
face
->
face_index
=
face_index
;
face
->
ntmFlags
=
0
;
if
(
ft_face
->
style_flags
&
FT_STYLE_FLAG_ITALIC
)
face
->
ntmFlags
|=
NTM_ITALIC
;
if
(
ft_face
->
style_flags
&
FT_STYLE_FLAG_BOLD
)
face
->
ntmFlags
|=
NTM_BOLD
;
if
(
face
->
ntmFlags
==
0
)
face
->
ntmFlags
=
NTM_REGULAR
;
face
->
font_version
=
pHeader
?
pHeader
->
Font_Revision
:
0
;
face
->
family
=
family
;
face
->
external
=
(
flags
&
ADDFONT_EXTERNAL_FONT
)
?
TRUE
:
FALSE
;
face
->
fs
=
fs
;
memset
(
&
face
->
fs_links
,
0
,
sizeof
(
face
->
fs_links
));
if
(
FT_IS_SCALABLE
(
ft_face
))
{
memset
(
&
face
->
size
,
0
,
sizeof
(
face
->
size
));
face
->
scalable
=
TRUE
;
}
else
{
TRACE
(
"Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld
\n
"
,
size
->
height
,
size
->
width
,
size
->
size
>>
6
,
size
->
x_ppem
>>
6
,
size
->
y_ppem
>>
6
);
face
->
size
.
height
=
size
->
height
;
face
->
size
.
width
=
size
->
width
;
face
->
size
.
size
=
size
->
size
;
face
->
size
.
x_ppem
=
size
->
x_ppem
;
face
->
size
.
y_ppem
=
size
->
y_ppem
;
face
->
size
.
internal_leading
=
internal_leading
;
face
->
scalable
=
FALSE
;
}
/* check for the presence of the 'CFF ' table to check if the font is Type1 */
tmp_size
=
0
;
if
(
!
pFT_Load_Sfnt_Table
(
ft_face
,
FT_MAKE_TAG
(
'C'
,
'F'
,
'F'
,
' '
),
0
,
NULL
,
&
tmp_size
))
{
TRACE
(
"Font %s/%p is OTF Type1
\n
"
,
wine_dbgstr_a
(
file
),
font_data_ptr
);
face
->
ntmFlags
|=
NTM_PS_OPENTYPE
;
}
TRACE
(
"fsCsb = %08x %08x/%08x %08x %08x %08x
\n
"
,
face
->
fs
.
fsCsb
[
0
],
face
->
fs
.
fsCsb
[
1
],
face
->
fs
.
fsUsb
[
0
],
face
->
fs
.
fsUsb
[
1
],
face
->
fs
.
fsUsb
[
2
],
face
->
fs
.
fsUsb
[
3
]);
if
(
face
->
fs
.
fsCsb
[
0
]
==
0
)
{
/* let's see if we can find any interesting cmaps */
for
(
i
=
0
;
i
<
ft_face
->
num_charmaps
;
i
++
)
{
switch
(
ft_face
->
charmaps
[
i
]
->
encoding
)
{
case
FT_ENCODING_UNICODE
:
case
FT_ENCODING_APPLE_ROMAN
:
face
->
fs
.
fsCsb
[
0
]
|=
FS_LATIN1
;
break
;
case
FT_ENCODING_MS_SYMBOL
:
face
->
fs
.
fsCsb
[
0
]
|=
FS_SYMBOL
;
break
;
default:
break
;
}
}
}
if
(
flags
&
ADDFONT_ADD_TO_CACHE
)
add_face_to_cache
(
face
);
AddFaceToFamily
(
face
,
family
);
}
while
(
!
FT_IS_SCALABLE
(
ft_face
)
&&
++
bitmap_num
<
ft_face
->
num_fixed_sizes
);
AddFaceToList
(
ft_face
,
fake_family
,
file
,
font_data_ptr
,
font_data_size
,
face_index
,
flags
);
num_faces
=
ft_face
->
num_faces
;
pFT_Done_Face
(
ft_face
);
TRACE
(
"Added font %s %s
\n
"
,
debugstr_w
(
family
->
FamilyName
),
debugstr_w
(
StyleW
));
}
while
(
num_faces
>
++
face_index
);
return
num_faces
;
}
...
...
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