Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Third Party Harfbuzz
提交
7aa3631d
T
Third Party Harfbuzz
项目概览
OpenHarmony
/
Third Party Harfbuzz
1 年多 前同步成功
通知
0
Star
18
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
Third Party Harfbuzz
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
7aa3631d
编写于
6月 28, 2016
作者:
D
Dominik Röttsches
提交者:
GitHub
6月 28, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into conflictingFontFix
上级
f7da0486
abae93fa
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
252 addition
and
318 deletion
+252
-318
src/hb-directwrite.cc
src/hb-directwrite.cc
+251
-317
src/hb-directwrite.h
src/hb-directwrite.h
+1
-1
未找到文件。
src/hb-directwrite.cc
浏览文件 @
7aa3631d
...
...
@@ -25,11 +25,7 @@
#define HB_SHAPER directwrite
#include "hb-shaper-impl-private.hh"
#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
#include <DWrite.h>
#else
#include <DWrite_1.h>
#endif
#include <DWrite_1.h>
#include "hb-directwrite.h"
...
...
@@ -45,176 +41,189 @@
HB_SHAPER_DATA_ENSURE_DECLARE
(
directwrite
,
face
)
HB_SHAPER_DATA_ENSURE_DECLARE
(
directwrite
,
font
)
/*
* shaper face data
*/
struct
hb_directwrite_shaper_face_data_t
{
HANDLE
fh
;
wchar_t
face_name
[
LF_FACESIZE
];
};
/* face_name should point to a wchar_t[LF_FACESIZE] object. */
static
void
_hb_generate_unique_face_name
(
wchar_t
*
face_name
,
unsigned
int
*
plen
)
{
/* We'll create a private name for the font from a UUID using a simple,
* somewhat base64-like encoding scheme */
const
char
*
enc
=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
;
UUID
id
;
UuidCreate
((
UUID
*
)
&
id
);
ASSERT_STATIC
(
2
+
3
*
(
16
/
2
)
<
LF_FACESIZE
);
unsigned
int
name_str_len
=
0
;
face_name
[
name_str_len
++
]
=
'F'
;
face_name
[
name_str_len
++
]
=
'_'
;
unsigned
char
*
p
=
(
unsigned
char
*
)
&
id
;
for
(
unsigned
int
i
=
0
;
i
<
16
;
i
+=
2
)
{
/* Spread the 16 bits from two bytes of the UUID across three chars of face_name,
* using the bits in groups of 5,5,6 to select chars from enc.
* This will generate 24 characters; with the 'F_' prefix we already provided,
* the name will be 26 chars (plus the NUL terminator), so will always fit within
* face_name (LF_FACESIZE = 32). */
face_name
[
name_str_len
++
]
=
enc
[
p
[
i
]
>>
3
];
face_name
[
name_str_len
++
]
=
enc
[((
p
[
i
]
<<
2
)
|
(
p
[
i
+
1
]
>>
6
))
&
0x1f
];
face_name
[
name_str_len
++
]
=
enc
[
p
[
i
+
1
]
&
0x3f
];
}
face_name
[
name_str_len
]
=
0
;
if
(
plen
)
*
plen
=
name_str_len
;
}
/* Destroys blob. */
static
hb_blob_t
*
_hb_rename_font
(
hb_blob_t
*
blob
,
wchar_t
*
new_name
)
{
/* Create a copy of the font data, with the 'name' table replaced by a
* table that names the font with our private F_* name created above.
* For simplicity, we just append a new 'name' table and update the
* sfnt directory; the original table is left in place, but unused.
*
* The new table will contain just 5 name IDs: family, style, unique,
* full, PS. All of them point to the same name data with our unique name.
/*
* DirectWrite font stream helpers
*/
blob
=
OT
::
Sanitizer
<
OT
::
OpenTypeFontFile
>::
sanitize
(
blob
);
unsigned
int
length
,
new_length
,
name_str_len
;
const
char
*
orig_sfnt_data
=
hb_blob_get_data
(
blob
,
&
length
);
_hb_generate_unique_face_name
(
new_name
,
&
name_str_len
);
// This is a font loader which provides only one font (unlike its original design).
// For a better implementation which was also source of this
// and DWriteFontFileStream, have a look at to NativeFontResourceDWrite.cpp in Mozilla
class
DWriteFontFileLoader
:
public
IDWriteFontFileLoader
{
private:
IDWriteFontFileStream
*
mFontFileStream
;
public:
DWriteFontFileLoader
(
IDWriteFontFileStream
*
fontFileStream
)
{
mFontFileStream
=
fontFileStream
;
}
static
const
uint16_t
name_IDs
[]
=
{
1
,
2
,
3
,
4
,
6
};
// IUnknown interface
IFACEMETHOD
(
QueryInterface
)(
IID
const
&
iid
,
OUT
void
**
ppObject
)
{
return
S_OK
;
}
IFACEMETHOD_
(
ULONG
,
AddRef
)()
{
return
1
;
}
IFACEMETHOD_
(
ULONG
,
Release
)()
{
return
1
;
}
unsigned
int
name_table_length
=
OT
::
name
::
min_size
+
ARRAY_LENGTH
(
name_IDs
)
*
OT
::
NameRecord
::
static_size
+
name_str_len
*
2
;
/* for name data in UTF16BE form */
unsigned
int
name_table_offset
=
(
length
+
3
)
&
~
3
;
// IDWriteFontFileLoader methods
virtual
HRESULT
STDMETHODCALLTYPE
CreateStreamFromKey
(
void
const
*
fontFileReferenceKey
,
UINT32
fontFileReferenceKeySize
,
OUT
IDWriteFontFileStream
**
fontFileStream
)
{
*
fontFileStream
=
mFontFileStream
;
return
S_OK
;
}
};
new_length
=
name_table_offset
+
((
name_table_length
+
3
)
&
~
3
);
void
*
new_sfnt_data
=
calloc
(
1
,
new_length
);
if
(
!
new_sfnt_data
)
class
DWriteFontFileStream
:
public
IDWriteFontFileStream
{
private:
uint8_t
*
mData
;
uint32_t
mSize
;
public:
DWriteFontFileStream
(
uint8_t
*
aData
,
uint32_t
aSize
)
{
hb_blob_destroy
(
blob
)
;
return
NULL
;
mData
=
aData
;
mSize
=
aSize
;
}
memcpy
(
new_sfnt_data
,
orig_sfnt_data
,
length
);
// IUnknown interface
IFACEMETHOD
(
QueryInterface
)(
IID
const
&
iid
,
OUT
void
**
ppObject
)
{
return
S_OK
;
}
IFACEMETHOD_
(
ULONG
,
AddRef
)()
{
return
1
;
}
IFACEMETHOD_
(
ULONG
,
Release
)()
{
return
1
;
}
OT
::
name
&
name
=
OT
::
StructAtOffset
<
OT
::
name
>
(
new_sfnt_data
,
name_table_offset
);
name
.
format
.
set
(
0
);
name
.
count
.
set
(
ARRAY_LENGTH
(
name_IDs
));
name
.
stringOffset
.
set
(
name
.
get_size
());
for
(
unsigned
int
i
=
0
;
i
<
ARRAY_LENGTH
(
name_IDs
);
i
++
)
// IDWriteFontFileStream methods
virtual
HRESULT
STDMETHODCALLTYPE
ReadFileFragment
(
void
const
**
fragmentStart
,
UINT64
fileOffset
,
UINT64
fragmentSize
,
OUT
void
**
fragmentContext
)
{
OT
::
NameRecord
&
record
=
name
.
nameRecord
[
i
];
record
.
platformID
.
set
(
3
);
record
.
encodingID
.
set
(
1
);
record
.
languageID
.
set
(
0x0409u
);
/* English */
record
.
nameID
.
set
(
name_IDs
[
i
]);
record
.
length
.
set
(
name_str_len
*
2
);
record
.
offset
.
set
(
0
);
// We are required to do bounds checking.
if
(
fileOffset
+
fragmentSize
>
mSize
)
{
return
E_FAIL
;
}
/* Copy string data from new_name, converting wchar_t to UTF16BE. */
unsigned
char
*
p
=
&
OT
::
StructAfter
<
unsigned
char
>
(
name
);
for
(
unsigned
int
i
=
0
;
i
<
name_str_len
;
i
++
)
{
*
p
++
=
new_name
[
i
]
>>
8
;
*
p
++
=
new_name
[
i
]
&
0xff
;
// truncate the 64 bit fileOffset to size_t sized index into mData
size_t
index
=
static_cast
<
size_t
>
(
fileOffset
);
// We should be alive for the duration of this.
*
fragmentStart
=
&
mData
[
index
];
*
fragmentContext
=
nullptr
;
return
S_OK
;
}
/* Adjust name table entry to point to new name table */
const
OT
::
OpenTypeFontFile
&
file
=
*
(
OT
::
OpenTypeFontFile
*
)
(
new_sfnt_data
);
unsigned
int
face_count
=
file
.
get_face_count
();
for
(
unsigned
int
face_index
=
0
;
face_index
<
face_count
;
face_index
++
)
{
/* Note: doing multiple edits (ie. TTC) can be unsafe. There may be
* toe-stepping. But we don't really care. */
const
OT
::
OpenTypeFontFace
&
face
=
file
.
get_face
(
face_index
);
unsigned
int
index
;
if
(
face
.
find_table_index
(
HB_OT_TAG_name
,
&
index
))
virtual
void
STDMETHODCALLTYPE
ReleaseFileFragment
(
void
*
fragmentContext
)
{
}
virtual
HRESULT
STDMETHODCALLTYPE
GetFileSize
(
OUT
UINT64
*
fileSize
)
{
OT
::
TableRecord
&
record
=
const_cast
<
OT
::
TableRecord
&>
(
face
.
get_table
(
index
));
record
.
checkSum
.
set_for_data
(
&
name
,
name_table_length
);
record
.
offset
.
set
(
name_table_offset
);
record
.
length
.
set
(
name_table_length
);
*
fileSize
=
mSize
;
return
S_OK
;
}
else
if
(
face_index
==
0
)
/* Fail if first face doesn't have 'name' table. */
virtual
HRESULT
STDMETHODCALLTYPE
GetLastWriteTime
(
OUT
UINT64
*
lastWriteTime
)
{
free
(
new_sfnt_data
);
hb_blob_destroy
(
blob
);
return
NULL
;
}
return
E_NOTIMPL
;
}
};
/* The checkSumAdjustment field in the 'head' table is now wrong,
* but that doesn't actually seem to cause any problems so we don't
* bother. */
hb_blob_destroy
(
blob
);
return
hb_blob_create
((
const
char
*
)
new_sfnt_data
,
new_length
,
HB_MEMORY_MODE_WRITABLE
,
NULL
,
free
);
}
/*
* shaper face data
*/
struct
hb_directwrite_shaper_face_data_t
{
IDWriteFactory
*
dwriteFactory
;
IDWriteFontFile
*
fontFile
;
IDWriteFontFileStream
*
fontFileStream
;
IDWriteFontFileLoader
*
fontFileLoader
;
IDWriteFontFace
*
fontFace
;
hb_blob_t
*
faceBlob
;
};
hb_directwrite_shaper_face_data_t
*
_hb_directwrite_shaper_face_data_create
(
hb_face_t
*
face
)
{
hb_directwrite_shaper_face_data_t
*
data
=
(
hb_directwrite_shaper_face_data_t
*
)
calloc
(
1
,
sizeof
(
hb_directwrite_shaper_face_data_t
));
(
hb_directwrite_shaper_face_data_t
*
)
malloc
(
sizeof
(
hb_directwrite_shaper_face_data_t
));
if
(
unlikely
(
!
data
))
return
NULL
;
// TODO: factory and fontFileLoader should be cached separately
IDWriteFactory
*
dwriteFactory
;
DWriteCreateFactory
(
DWRITE_FACTORY_TYPE_SHARED
,
__uuidof
(
IDWriteFactory
),
(
IUnknown
**
)
&
dwriteFactory
);
HRESULT
hr
;
hb_blob_t
*
blob
=
hb_face_reference_blob
(
face
);
if
(
unlikely
(
!
hb_blob_get_length
(
blob
)))
DEBUG_MSG
(
DIRECTWRITE
,
face
,
"Face has empty blob"
);
IDWriteFontFileStream
*
fontFileStream
=
new
DWriteFontFileStream
(
(
uint8_t
*
)
hb_blob_get_data
(
blob
,
NULL
),
hb_blob_get_length
(
blob
)
);
blob
=
_hb_rename_font
(
blob
,
data
->
face_name
);
if
(
unlikely
(
!
blob
))
{
free
(
data
);
return
NULL
;
IDWriteFontFileLoader
*
fontFileLoader
=
new
DWriteFontFileLoader
(
fontFileStream
);
dwriteFactory
->
RegisterFontFileLoader
(
fontFileLoader
);
IDWriteFontFile
*
fontFile
;
uint64_t
fontFileKey
=
0
;
hr
=
dwriteFactory
->
CreateCustomFontFileReference
(
&
fontFileKey
,
sizeof
(
fontFileKey
),
fontFileLoader
,
&
fontFile
);
#define FAIL(...) \
HB_STMT_START { \
DEBUG_MSG (DIRECTWRITE, NULL, __VA_ARGS__); \
return false; \
} HB_STMT_END;
if
(
FAILED
(
hr
))
{
FAIL
(
"Failed to load font file from data!"
);
return
false
;
}
DWORD
num_fonts_installed
;
data
->
fh
=
AddFontMemResourceEx
((
void
*
)
hb_blob_get_data
(
blob
,
NULL
),
hb_blob_get_length
(
blob
),
0
,
&
num_fonts_installed
);
if
(
unlikely
(
!
data
->
fh
))
{
DEBUG_MSG
(
DIRECTWRITE
,
face
,
"Face AddFontMemResourceEx() failed"
);
free
(
data
);
return
NULL
;
BOOL
isSupported
;
DWRITE_FONT_FILE_TYPE
fileType
;
DWRITE_FONT_FACE_TYPE
faceType
;
UINT32
numberOfFaces
;
hr
=
fontFile
->
Analyze
(
&
isSupported
,
&
fileType
,
&
faceType
,
&
numberOfFaces
);
if
(
FAILED
(
hr
)
||
!
isSupported
)
{
FAIL
(
"Font file is not supported."
);
return
false
;
}
#undef FAIL
IDWriteFontFace
*
fontFace
;
dwriteFactory
->
CreateFontFace
(
faceType
,
1
,
&
fontFile
,
0
,
DWRITE_FONT_SIMULATIONS_NONE
,
&
fontFace
);
data
->
dwriteFactory
=
dwriteFactory
;
data
->
fontFile
=
fontFile
;
data
->
fontFileStream
=
fontFileStream
;
data
->
fontFileLoader
=
fontFileLoader
;
data
->
fontFace
=
fontFace
;
data
->
faceBlob
=
blob
;
return
data
;
}
void
_hb_directwrite_shaper_face_data_destroy
(
hb_directwrite_shaper_face_data_t
*
data
)
{
RemoveFontMemResourceEx
(
data
->
fh
);
free
(
data
);
if
(
data
->
fontFace
)
data
->
fontFace
->
Release
();
if
(
data
->
fontFile
)
data
->
fontFile
->
Release
();
if
(
data
->
dwriteFactory
)
{
if
(
data
->
fontFileLoader
)
data
->
dwriteFactory
->
UnregisterFontFileLoader
(
data
->
fontFileLoader
);
data
->
dwriteFactory
->
Release
();
}
if
(
data
->
fontFileLoader
)
delete
data
->
fontFileLoader
;
if
(
data
->
fontFileStream
)
delete
data
->
fontFileStream
;
if
(
data
->
faceBlob
)
hb_blob_destroy
(
data
->
faceBlob
);
if
(
data
)
free
(
data
);
}
...
...
@@ -223,90 +232,27 @@ _hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data
*/
struct
hb_directwrite_shaper_font_data_t
{
HDC
hdc
;
LOGFONTW
log_font
;
HFONT
hfont
;
};
static
bool
populate_log_font
(
LOGFONTW
*
lf
,
hb_font_t
*
font
)
{
memset
(
lf
,
0
,
sizeof
(
*
lf
));
lf
->
lfHeight
=
-
font
->
y_scale
;
lf
->
lfCharSet
=
DEFAULT_CHARSET
;
hb_face_t
*
face
=
font
->
face
;
hb_directwrite_shaper_face_data_t
*
face_data
=
HB_SHAPER_DATA_GET
(
face
);
memcpy
(
lf
->
lfFaceName
,
face_data
->
face_name
,
sizeof
(
lf
->
lfFaceName
));
return
true
;
}
hb_directwrite_shaper_font_data_t
*
_hb_directwrite_shaper_font_data_create
(
hb_font_t
*
font
)
{
if
(
unlikely
(
!
hb_directwrite_shaper_face_data_ensure
(
font
->
face
)))
return
NULL
;
hb_directwrite_shaper_font_data_t
*
data
=
(
hb_directwrite_shaper_font_data_t
*
)
calloc
(
1
,
sizeof
(
hb_directwrite_shaper_font_data_t
));
(
hb_directwrite_shaper_font_data_t
*
)
malloc
(
sizeof
(
hb_directwrite_shaper_font_data_t
));
if
(
unlikely
(
!
data
))
return
NULL
;
data
->
hdc
=
GetDC
(
NULL
);
if
(
unlikely
(
!
populate_log_font
(
&
data
->
log_font
,
font
)))
{
DEBUG_MSG
(
DIRECTWRITE
,
font
,
"Font populate_log_font() failed"
);
_hb_directwrite_shaper_font_data_destroy
(
data
);
return
NULL
;
}
data
->
hfont
=
CreateFontIndirectW
(
&
data
->
log_font
);
if
(
unlikely
(
!
data
->
hfont
))
{
DEBUG_MSG
(
DIRECTWRITE
,
font
,
"Font CreateFontIndirectW() failed"
);
_hb_directwrite_shaper_font_data_destroy
(
data
);
return
NULL
;
}
if
(
!
SelectObject
(
data
->
hdc
,
data
->
hfont
))
{
DEBUG_MSG
(
DIRECTWRITE
,
font
,
"Font SelectObject() failed"
);
_hb_directwrite_shaper_font_data_destroy
(
data
);
return
NULL
;
}
return
data
;
}
void
_hb_directwrite_shaper_font_data_destroy
(
hb_directwrite_shaper_font_data_t
*
data
)
{
if
(
data
->
hdc
)
ReleaseDC
(
NULL
,
data
->
hdc
);
if
(
data
->
hfont
)
DeleteObject
(
data
->
hfont
);
free
(
data
);
}
LOGFONTW
*
hb_directwrite_font_get_logfontw
(
hb_font_t
*
font
)
{
if
(
unlikely
(
!
hb_directwrite_shaper_font_data_ensure
(
font
)))
return
NULL
;
hb_directwrite_shaper_font_data_t
*
font_data
=
HB_SHAPER_DATA_GET
(
font
);
return
&
font_data
->
log_font
;
}
HFONT
hb_directwrite_font_get_hfont
(
hb_font_t
*
font
)
{
if
(
unlikely
(
!
hb_directwrite_shaper_font_data_ensure
(
font
)))
return
NULL
;
hb_directwrite_shaper_font_data_t
*
font_data
=
HB_SHAPER_DATA_GET
(
font
);
return
font_data
->
hfont
;
}
/*
* shaper shape_plan data
...
...
@@ -327,7 +273,7 @@ _hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan
{
}
// Most of
here
TextAnalysis is originally written by Bas Schouten for Mozilla project
// Most of TextAnalysis is originally written by Bas Schouten for Mozilla project
// but now is relicensed to MIT for HarfBuzz use
class
TextAnalysis
:
public
IDWriteTextAnalysisSource
,
public
IDWriteTextAnalysisSink
...
...
@@ -444,7 +390,8 @@ public:
IFACEMETHODIMP
GetLocaleName
(
uint32_t
textPosition
,
uint32_t
*
textLength
,
wchar_t
const
**
localeName
)
{
wchar_t
const
**
localeName
)
{
return
S_OK
;
}
...
...
@@ -469,7 +416,8 @@ public:
{
SetCurrentRun
(
textPosition
);
SplitCurrentRun
(
textPosition
);
while
(
textLength
>
0
)
{
while
(
textLength
>
0
)
{
Run
*
run
=
FetchNextRun
(
&
textLength
);
run
->
mScript
=
*
scriptAnalysis
;
}
...
...
@@ -502,10 +450,12 @@ protected:
Run
*
origRun
=
mCurrentRun
;
// Split the tail if needed (the length remaining is less than the
// current run's size).
if
(
*
textLength
<
mCurrentRun
->
mTextLength
)
{
SplitCurrentRun
(
mCurrentRun
->
mTextStart
+
*
textLength
);
if
(
*
textLength
<
mCurrentRun
->
mTextLength
)
{
SplitCurrentRun
(
mCurrentRun
->
mTextStart
+
*
textLength
);
}
else
{
else
{
// Just advance the current run.
mCurrentRun
=
mCurrentRun
->
nextRun
;
}
...
...
@@ -522,12 +472,14 @@ protected:
// this will usually just return early. If not, find the
// corresponding run for the text position.
if
(
mCurrentRun
&&
mCurrentRun
->
ContainsTextPosition
(
textPosition
))
{
if
(
mCurrentRun
&&
mCurrentRun
->
ContainsTextPosition
(
textPosition
))
{
return
;
}
for
(
Run
*
run
=
&
mRunHead
;
run
;
run
=
run
->
nextRun
)
{
if
(
run
->
ContainsTextPosition
(
textPosition
))
{
if
(
run
->
ContainsTextPosition
(
textPosition
))
{
mCurrentRun
=
run
;
return
;
}
...
...
@@ -538,13 +490,15 @@ protected:
void
SplitCurrentRun
(
uint32_t
splitPosition
)
{
if
(
!
mCurrentRun
)
{
if
(
!
mCurrentRun
)
{
//NS_ASSERTION(false, "SplitCurrentRun called without current run.");
// Shouldn't be calling this when no current run is set!
return
;
}
// Split the current run.
if
(
splitPosition
<=
mCurrentRun
->
mTextStart
)
{
if
(
splitPosition
<=
mCurrentRun
->
mTextStart
)
{
// No need to split, already the start of a run
// or before it. Usually the first.
return
;
...
...
@@ -600,32 +554,11 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
hb_face_t
*
face
=
font
->
face
;
hb_directwrite_shaper_face_data_t
*
face_data
=
HB_SHAPER_DATA_GET
(
face
);
hb_directwrite_shaper_font_data_t
*
font_data
=
HB_SHAPER_DATA_GET
(
font
);
IDWriteFactory
*
dwriteFactory
=
face_data
->
dwriteFactory
;
IDWriteFontFace
*
fontFace
=
face_data
->
fontFace
;
// factory probably should be cached
#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
IDWriteFactory
*
dwriteFactory
;
#else
IDWriteFactory1
*
dwriteFactory
;
#endif
DWriteCreateFactory
(
DWRITE_FACTORY_TYPE_SHARED
,
__uuidof
(
IDWriteFactory
),
(
IUnknown
**
)
&
dwriteFactory
);
IDWriteGdiInterop
*
gdiInterop
;
dwriteFactory
->
GetGdiInterop
(
&
gdiInterop
);
IDWriteFontFace
*
fontFace
;
gdiInterop
->
CreateFontFaceFromHdc
(
font_data
->
hdc
,
&
fontFace
);
#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
IDWriteTextAnalyzer
*
analyzer
;
dwriteFactory
->
CreateTextAnalyzer
(
&
analyzer
);
#else
IDWriteTextAnalyzer
*
analyzer0
;
dwriteFactory
->
CreateTextAnalyzer
(
&
analyzer0
);
IDWriteTextAnalyzer1
*
analyzer
=
(
IDWriteTextAnalyzer1
*
)
analyzer0
;
#endif
unsigned
int
scratch_size
;
hb_buffer_t
::
scratch_buffer_t
*
scratch
=
buffer
->
get_scratch_buffer
(
&
scratch_size
);
...
...
@@ -672,7 +605,6 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
}
}
HRESULT
hr
;
// TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
DWRITE_READING_DIRECTION
readingDirection
=
buffer
->
props
.
direction
?
...
...
@@ -688,6 +620,7 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
TextAnalysis
analysis
(
textString
,
textLength
,
NULL
,
readingDirection
);
TextAnalysis
::
Run
*
runHead
;
HRESULT
hr
;
hr
=
analysis
.
GenerateResults
(
analyzer
,
&
runHead
);
#define FAIL(...) \
...
...
@@ -731,11 +664,11 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
(
const
DWRITE_TYPOGRAPHIC_FEATURES
*
)
&
singleFeatures
;
const
uint32_t
featureRangeLengths
[]
=
{
textLength
};
uint16_t
*
clusterMap
=
(
uint16_t
*
)
malloc
(
textLength
*
sizeof
(
uint16_t
));
DWRITE_SHAPING_TEXT_PROPERTIES
*
textProperties
=
(
DWRITE_SHAPING_TEXT_PROPERTIES
*
)
malloc
(
textLength
*
sizeof
(
DWRITE_SHAPING_TEXT_PROPERTIES
));
retry_getglyphs:
uint16_t
*
clusterMap
=
(
uint16_t
*
)
malloc
(
maxGlyphCount
*
sizeof
(
uint16_t
));
uint16_t
*
glyphIndices
=
(
uint16_t
*
)
malloc
(
maxGlyphCount
*
sizeof
(
uint16_t
));
DWRITE_SHAPING_TEXT_PROPERTIES
*
textProperties
=
(
DWRITE_SHAPING_TEXT_PROPERTIES
*
)
malloc
(
maxGlyphCount
*
sizeof
(
DWRITE_SHAPING_TEXT_PROPERTIES
));
DWRITE_SHAPING_GLYPH_PROPERTIES
*
glyphProperties
=
(
DWRITE_SHAPING_GLYPH_PROPERTIES
*
)
malloc
(
maxGlyphCount
*
sizeof
(
DWRITE_SHAPING_GLYPH_PROPERTIES
));
...
...
@@ -746,9 +679,7 @@ retry_getglyphs:
if
(
unlikely
(
hr
==
HRESULT_FROM_WIN32
(
ERROR_INSUFFICIENT_BUFFER
)))
{
free
(
clusterMap
);
free
(
glyphIndices
);
free
(
textProperties
);
free
(
glyphProperties
);
maxGlyphCount
*=
2
;
...
...
@@ -799,12 +730,19 @@ retry_getglyphs:
return
false
;
}
#ifdef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
// TODO: get lineWith from somewhere
float
lineWidth
=
0
;
IDWriteTextAnalyzer1
*
analyzer1
;
analyzer
->
QueryInterface
(
&
analyzer1
);
if
(
analyzer1
&&
lineWidth
)
{
DWRITE_JUSTIFICATION_OPPORTUNITY
*
justificationOpportunities
=
(
DWRITE_JUSTIFICATION_OPPORTUNITY
*
)
malloc
(
maxGlyphCount
*
sizeof
(
DWRITE_JUSTIFICATION_OPPORTUNITY
));
hr
=
analyzer
->
GetJustificationOpportunities
(
fontFace
,
fontEmSize
,
hr
=
analyzer1
->
GetJustificationOpportunities
(
fontFace
,
fontEmSize
,
runHead
->
mScript
,
textLength
,
glyphCount
,
textString
,
clusterMap
,
glyphProperties
,
justificationOpportunities
);
...
...
@@ -814,27 +752,24 @@ retry_getglyphs:
return
false
;
}
// TODO: get lineWith from somewhere
float
lineWidth
=
60000
;
float
*
justifiedGlyphAdvances
=
(
float
*
)
malloc
(
maxGlyphCount
*
sizeof
(
float
));
DWRITE_GLYPH_OFFSET
*
justifiedGlyphOffsets
=
(
DWRITE_GLYPH_OFFSET
*
)
malloc
(
glyphCount
*
sizeof
(
DWRITE_GLYPH_OFFSET
));
hr
=
analyzer
->
JustifyGlyphAdvances
(
lineWidth
,
glyphCount
,
justificationOpportunities
,
hr
=
analyzer1
->
JustifyGlyphAdvances
(
lineWidth
,
glyphCount
,
justificationOpportunities
,
glyphAdvances
,
glyphOffsets
,
justifiedGlyphAdvances
,
justifiedGlyphOffsets
);
if
(
FAILED
(
hr
))
{
FAIL
(
"Analyzer failed to get justified glyph advances."
);
FAIL
(
"Analyzer failed to get justified glyph advances."
);
return
false
;
}
DWRITE_SCRIPT_PROPERTIES
scriptProperties
;
hr
=
analyzer
->
GetScriptProperties
(
runHead
->
mScript
,
&
scriptProperties
);
hr
=
analyzer1
->
GetScriptProperties
(
runHead
->
mScript
,
&
scriptProperties
);
if
(
FAILED
(
hr
))
{
FAIL
(
"Analyzer failed to get script properties."
);
FAIL
(
"Analyzer failed to get script properties."
);
return
false
;
}
uint32_t
justificationCharacter
=
scriptProperties
.
justificationCharacter
;
...
...
@@ -842,14 +777,14 @@ retry_getglyphs:
// if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
if
(
justificationCharacter
!=
32
)
{
retry_getjustifiedglyphs:
uint16_t
*
modifiedClusterMap
=
(
uint16_t
*
)
malloc
(
maxGlyphCount
*
sizeof
(
uint16_t
));
uint16_t
*
modifiedClusterMap
=
(
uint16_t
*
)
malloc
(
textLength
*
sizeof
(
uint16_t
));
retry_getjustifiedglyphs:
uint16_t
*
modifiedGlyphIndices
=
(
uint16_t
*
)
malloc
(
maxGlyphCount
*
sizeof
(
uint16_t
));
float
*
modifiedGlyphAdvances
=
(
float
*
)
malloc
(
maxGlyphCount
*
sizeof
(
float
));
DWRITE_GLYPH_OFFSET
*
modifiedGlyphOffsets
=
(
DWRITE_GLYPH_OFFSET
*
)
malloc
(
maxGlyphCount
*
sizeof
(
DWRITE_GLYPH_OFFSET
));
uint32_t
actualGlyphsCount
;
hr
=
analyzer
->
GetJustifiedGlyphs
(
fontFace
,
fontEmSize
,
runHead
->
mScript
,
hr
=
analyzer1
->
GetJustifiedGlyphs
(
fontFace
,
fontEmSize
,
runHead
->
mScript
,
textLength
,
glyphCount
,
maxGlyphCount
,
clusterMap
,
glyphIndices
,
glyphAdvances
,
justifiedGlyphAdvances
,
justifiedGlyphOffsets
,
glyphProperties
,
&
actualGlyphsCount
,
modifiedClusterMap
,
modifiedGlyphIndices
,
...
...
@@ -858,7 +793,6 @@ retry_getjustifiedglyphs:
if
(
hr
==
HRESULT_FROM_WIN32
(
ERROR_INSUFFICIENT_BUFFER
))
{
maxGlyphCount
=
actualGlyphsCount
;
free
(
modifiedClusterMap
);
free
(
modifiedGlyphIndices
);
free
(
modifiedGlyphAdvances
);
free
(
modifiedGlyphOffsets
);
...
...
@@ -884,21 +818,21 @@ retry_getjustifiedglyphs:
glyphAdvances
=
modifiedGlyphAdvances
;
glyphOffsets
=
modifiedGlyphOffsets
;
free
(
justifiedGlyphAdvances
);
free
(
justifiedGlyphOffsets
);
free
(
justifiedGlyphAdvances
);
free
(
justifiedGlyphOffsets
);
}
else
{
free
(
glyphAdvances
);
free
(
glyphOffsets
);
free
(
glyphAdvances
);
free
(
glyphOffsets
);
glyphAdvances
=
justifiedGlyphAdvances
;
glyphOffsets
=
justifiedGlyphOffsets
;
}
free
(
justificationOpportunities
);
free
(
justificationOpportunities
);
#endif
}
/* Ok, we've got everything we need, now compose output buffer,
* very, *very*, carefully! */
...
...
src/hb-directwrite.h
浏览文件 @
7aa3631d
...
...
@@ -31,4 +31,4 @@ HB_BEGIN_DECLS
HB_END_DECLS
#endif
/* HB_
UNISCRIB
E_H */
#endif
/* HB_
DIRECTWRIT
E_H */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录