Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
04f02ec2
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
04f02ec2
编写于
1月 17, 2017
作者:
A
Alex Dima
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixes #18644: Fix char width reading in IE11 and Edge
上级
e2c39c6c
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
282 addition
and
76 deletion
+282
-76
src/vs/editor/browser/config/charWidthReader.ts
src/vs/editor/browser/config/charWidthReader.ts
+215
-0
src/vs/editor/browser/config/configuration.ts
src/vs/editor/browser/config/configuration.ts
+67
-76
未找到文件。
src/vs/editor/browser/config/charWidthReader.ts
0 → 100644
浏览文件 @
04f02ec2
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
*
as
browser
from
'
vs/base/browser/browser
'
;
import
{
BareFontInfo
}
from
'
vs/editor/common/config/fontInfo
'
;
export
const
enum
CharWidthRequestType
{
Regular
=
0
,
Italic
=
1
,
Bold
=
2
}
export
class
CharWidthRequest
{
public
readonly
chr
:
string
;
public
readonly
type
:
CharWidthRequestType
;
public
width
:
number
;
constructor
(
chr
:
string
,
type
:
CharWidthRequestType
)
{
this
.
chr
=
chr
;
this
.
type
=
type
;
this
.
width
=
0
;
}
public
fulfill
(
width
:
number
)
{
this
.
width
=
width
;
}
}
interface
ICharWidthReader
{
read
():
void
;
}
class
DomCharWidthReader
implements
ICharWidthReader
{
private
readonly
_bareFontInfo
:
BareFontInfo
;
private
readonly
_requests
:
CharWidthRequest
[];
private
_container
:
HTMLElement
;
private
_testElements
:
HTMLSpanElement
[];
constructor
(
bareFontInfo
:
BareFontInfo
,
requests
:
CharWidthRequest
[])
{
this
.
_bareFontInfo
=
bareFontInfo
;
this
.
_requests
=
requests
;
this
.
_container
=
null
;
this
.
_testElements
=
null
;
}
public
read
():
void
{
// Create a test container with all these test elements
this
.
_createDomElements
();
// Add the container to the DOM
document
.
body
.
appendChild
(
this
.
_container
);
// Read character widths
this
.
_readFromDomElements
();
// Remove the container from the DOM
document
.
body
.
removeChild
(
this
.
_container
);
this
.
_container
=
null
;
this
.
_testElements
=
null
;
}
private
_createDomElements
():
void
{
let
container
=
document
.
createElement
(
'
div
'
);
container
.
style
.
position
=
'
absolute
'
;
container
.
style
.
top
=
'
-50000px
'
;
container
.
style
.
width
=
'
50000px
'
;
let
regularDomNode
=
document
.
createElement
(
'
div
'
);
regularDomNode
.
style
.
fontFamily
=
this
.
_bareFontInfo
.
fontFamily
;
regularDomNode
.
style
.
fontWeight
=
this
.
_bareFontInfo
.
fontWeight
;
regularDomNode
.
style
.
fontSize
=
this
.
_bareFontInfo
.
fontSize
+
'
px
'
;
regularDomNode
.
style
.
lineHeight
=
this
.
_bareFontInfo
.
lineHeight
+
'
px
'
;
container
.
appendChild
(
regularDomNode
);
let
boldDomNode
=
document
.
createElement
(
'
div
'
);
boldDomNode
.
style
.
fontFamily
=
this
.
_bareFontInfo
.
fontFamily
;
boldDomNode
.
style
.
fontWeight
=
'
bold
'
;
boldDomNode
.
style
.
fontSize
=
this
.
_bareFontInfo
.
fontSize
+
'
px
'
;
boldDomNode
.
style
.
lineHeight
=
this
.
_bareFontInfo
.
lineHeight
+
'
px
'
;
container
.
appendChild
(
boldDomNode
);
let
italicDomNode
=
document
.
createElement
(
'
div
'
);
italicDomNode
.
style
.
fontFamily
=
this
.
_bareFontInfo
.
fontFamily
;
italicDomNode
.
style
.
fontWeight
=
this
.
_bareFontInfo
.
fontWeight
;
italicDomNode
.
style
.
fontSize
=
this
.
_bareFontInfo
.
fontSize
+
'
px
'
;
italicDomNode
.
style
.
lineHeight
=
this
.
_bareFontInfo
.
lineHeight
+
'
px
'
;
italicDomNode
.
style
.
fontStyle
=
'
italic
'
;
container
.
appendChild
(
italicDomNode
);
let
testElements
:
HTMLSpanElement
[]
=
[];
for
(
let
i
=
0
,
len
=
this
.
_requests
.
length
;
i
<
len
;
i
++
)
{
const
request
=
this
.
_requests
[
i
];
let
parent
:
HTMLElement
;
if
(
request
.
type
===
CharWidthRequestType
.
Regular
)
{
parent
=
regularDomNode
;
}
if
(
request
.
type
===
CharWidthRequestType
.
Bold
)
{
parent
=
boldDomNode
;
}
if
(
request
.
type
===
CharWidthRequestType
.
Italic
)
{
parent
=
italicDomNode
;
}
parent
.
appendChild
(
document
.
createElement
(
'
br
'
));
let
testElement
=
document
.
createElement
(
'
span
'
);
DomCharWidthReader
.
_render
(
testElement
,
request
);
parent
.
appendChild
(
testElement
);
testElements
[
i
]
=
testElement
;
}
this
.
_container
=
container
;
this
.
_testElements
=
testElements
;
}
private
static
_render
(
testElement
:
HTMLElement
,
request
:
CharWidthRequest
):
void
{
if
(
request
.
chr
===
'
'
)
{
let
htmlString
=
'
'
;
// Repeat character 256 (2^8) times
for
(
let
i
=
0
;
i
<
8
;
i
++
)
{
htmlString
+=
htmlString
;
}
testElement
.
innerHTML
=
htmlString
;
}
else
{
let
testString
=
request
.
chr
;
// Repeat character 256 (2^8) times
for
(
let
i
=
0
;
i
<
8
;
i
++
)
{
testString
+=
testString
;
}
testElement
.
textContent
=
testString
;
}
}
private
_readFromDomElements
():
void
{
for
(
let
i
=
0
,
len
=
this
.
_requests
.
length
;
i
<
len
;
i
++
)
{
const
request
=
this
.
_requests
[
i
];
const
testElement
=
this
.
_testElements
[
i
];
request
.
fulfill
(
testElement
.
offsetWidth
/
256
);
}
}
}
class
CanvasCharWidthReader
implements
ICharWidthReader
{
private
readonly
_bareFontInfo
:
BareFontInfo
;
private
readonly
_requests
:
CharWidthRequest
[];
constructor
(
bareFontInfo
:
BareFontInfo
,
requests
:
CharWidthRequest
[])
{
this
.
_bareFontInfo
=
bareFontInfo
;
this
.
_requests
=
requests
;
}
public
read
():
void
{
let
canvasElement
=
<
HTMLCanvasElement
>
document
.
createElement
(
'
canvas
'
);
let
context
=
canvasElement
.
getContext
(
'
2d
'
);
context
.
font
=
CanvasCharWidthReader
.
_createFontString
(
this
.
_bareFontInfo
);
for
(
let
i
=
0
,
len
=
this
.
_requests
.
length
;
i
<
len
;
i
++
)
{
const
request
=
this
.
_requests
[
i
];
if
(
request
.
type
===
CharWidthRequestType
.
Regular
)
{
request
.
fulfill
(
context
.
measureText
(
request
.
chr
).
width
);
}
}
context
.
font
=
CanvasCharWidthReader
.
_createFontString
(
this
.
_bareFontInfo
,
undefined
,
'
bold
'
);
for
(
let
i
=
0
,
len
=
this
.
_requests
.
length
;
i
<
len
;
i
++
)
{
const
request
=
this
.
_requests
[
i
];
if
(
request
.
type
===
CharWidthRequestType
.
Bold
)
{
request
.
fulfill
(
context
.
measureText
(
request
.
chr
).
width
);
}
}
context
.
font
=
CanvasCharWidthReader
.
_createFontString
(
this
.
_bareFontInfo
,
'
italic
'
);
for
(
let
i
=
0
,
len
=
this
.
_requests
.
length
;
i
<
len
;
i
++
)
{
const
request
=
this
.
_requests
[
i
];
if
(
request
.
type
===
CharWidthRequestType
.
Italic
)
{
request
.
fulfill
(
context
.
measureText
(
request
.
chr
).
width
);
}
}
}
private
static
_createFontString
(
bareFontInfo
:
BareFontInfo
,
overwriteFontStyle
:
string
=
'
normal
'
,
overwriteFontWeight
:
string
=
bareFontInfo
.
fontWeight
):
string
{
return
this
.
_doCreateFontString
(
overwriteFontStyle
,
overwriteFontWeight
,
bareFontInfo
.
fontSize
,
bareFontInfo
.
lineHeight
,
bareFontInfo
.
fontFamily
);
}
private
static
_doCreateFontString
(
fontStyle
:
string
,
fontWeight
:
string
,
fontSize
:
number
,
lineHeight
:
number
,
fontFamily
:
string
):
string
{
// The full font syntax is:
// style | variant | weight | stretch | size/line-height | fontFamily
// (https://developer.mozilla.org/en-US/docs/Web/CSS/font)
// But it appears Edge and IE11 cannot properly parse `stretch`.
return
`
${
fontStyle
}
normal
${
fontWeight
}
${
fontSize
}
px /
${
lineHeight
}
px
${
fontFamily
}
`
;
}
}
export
function
readCharWidths
(
bareFontInfo
:
BareFontInfo
,
requests
:
CharWidthRequest
[]):
void
{
// In IE11, it appears that ctx.measureText() always returns integer results.
if
(
browser
.
isIE
)
{
let
reader
=
new
DomCharWidthReader
(
bareFontInfo
,
requests
);
reader
.
read
();
}
else
{
let
reader
=
new
CanvasCharWidthReader
(
bareFontInfo
,
requests
);
reader
.
read
();
}
}
src/vs/editor/browser/config/configuration.ts
浏览文件 @
04f02ec2
...
...
@@ -13,6 +13,7 @@ import { IDimension } from 'vs/editor/common/editorCommon';
import
{
FontInfo
,
BareFontInfo
}
from
'
vs/editor/common/config/fontInfo
'
;
import
{
ElementSizeObserver
}
from
'
vs/editor/browser/config/elementSizeObserver
'
;
import
{
FastDomNode
}
from
'
vs/base/browser/styleMutator
'
;
import
{
CharWidthRequest
,
CharWidthRequestType
,
readCharWidths
}
from
'
vs/editor/browser/config/charWidthReader
'
;
class
CSSBasedConfigurationCache
{
...
...
@@ -125,85 +126,75 @@ class CSSBasedConfiguration extends Disposable {
}
}
private
static
createRequest
(
chr
:
string
,
type
:
CharWidthRequestType
,
all
:
CharWidthRequest
[],
monospace
:
CharWidthRequest
[]):
CharWidthRequest
{
let
result
=
new
CharWidthRequest
(
chr
,
type
);
all
.
push
(
result
);
if
(
monospace
)
{
monospace
.
push
(
result
);
}
return
result
;
}
private
static
_actualReadConfiguration
(
bareFontInfo
:
BareFontInfo
):
FontInfo
{
let
canvasElem
=
<
HTMLCanvasElement
>
document
.
createElement
(
'
canvas
'
);
let
context
=
canvasElem
.
getContext
(
'
2d
'
);
let
all
:
CharWidthRequest
[]
=
[];
let
monospace
:
CharWidthRequest
[]
=
[];
const
typicalHalfwidthCharacter
=
this
.
createRequest
(
'
n
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
typicalFullwidthCharacter
=
this
.
createRequest
(
'
\
uff4d
'
,
CharWidthRequestType
.
Regular
,
all
,
null
);
const
space
=
this
.
createRequest
(
'
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit0
=
this
.
createRequest
(
'
0
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit1
=
this
.
createRequest
(
'
1
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit2
=
this
.
createRequest
(
'
2
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit3
=
this
.
createRequest
(
'
3
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit4
=
this
.
createRequest
(
'
4
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit5
=
this
.
createRequest
(
'
5
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit6
=
this
.
createRequest
(
'
6
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit7
=
this
.
createRequest
(
'
7
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit8
=
this
.
createRequest
(
'
8
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
const
digit9
=
this
.
createRequest
(
'
9
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
let
getCharWidth
=
(
char
:
string
):
number
=>
{
return
context
.
measureText
(
char
).
width
;
}
;
// monospace test: used for whitespace rendering
this
.
createRequest
(
'
→
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
)
;
this
.
createRequest
(
'
·
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
)
;
context
.
font
=
`normal normal normal normal
${
bareFontInfo
.
fontSize
}
px /
${
bareFontInfo
.
lineHeight
}
px
${
bareFontInfo
.
fontFamily
}
`
;
const
typicalHalfwidthCharacter
=
getCharWidth
(
'
n
'
);
const
typicalFullwidthCharacter
=
getCharWidth
(
'
\
uff4d
'
);
// monospace test: some characters
this
.
createRequest
(
'
|
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
this
.
createRequest
(
'
/
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
this
.
createRequest
(
'
-
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
this
.
createRequest
(
'
_
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
this
.
createRequest
(
'
i
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
this
.
createRequest
(
'
l
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
this
.
createRequest
(
'
m
'
,
CharWidthRequestType
.
Regular
,
all
,
monospace
);
// monospace italic test
this
.
createRequest
(
'
|
'
,
CharWidthRequestType
.
Italic
,
all
,
monospace
);
this
.
createRequest
(
'
_
'
,
CharWidthRequestType
.
Italic
,
all
,
monospace
);
this
.
createRequest
(
'
i
'
,
CharWidthRequestType
.
Italic
,
all
,
monospace
);
this
.
createRequest
(
'
l
'
,
CharWidthRequestType
.
Italic
,
all
,
monospace
);
this
.
createRequest
(
'
m
'
,
CharWidthRequestType
.
Italic
,
all
,
monospace
);
this
.
createRequest
(
'
n
'
,
CharWidthRequestType
.
Italic
,
all
,
monospace
);
// monospace bold test
this
.
createRequest
(
'
|
'
,
CharWidthRequestType
.
Bold
,
all
,
monospace
);
this
.
createRequest
(
'
_
'
,
CharWidthRequestType
.
Bold
,
all
,
monospace
);
this
.
createRequest
(
'
i
'
,
CharWidthRequestType
.
Bold
,
all
,
monospace
);
this
.
createRequest
(
'
l
'
,
CharWidthRequestType
.
Bold
,
all
,
monospace
);
this
.
createRequest
(
'
m
'
,
CharWidthRequestType
.
Bold
,
all
,
monospace
);
this
.
createRequest
(
'
n
'
,
CharWidthRequestType
.
Bold
,
all
,
monospace
);
readCharWidths
(
bareFontInfo
,
all
);
const
maxDigitWidth
=
Math
.
max
(
digit0
.
width
,
digit1
.
width
,
digit2
.
width
,
digit3
.
width
,
digit4
.
width
,
digit5
.
width
,
digit6
.
width
,
digit7
.
width
,
digit8
.
width
,
digit9
.
width
);
let
isMonospace
=
true
;
let
monospaceWidth
=
typicalHalfwidthCharacter
;
let
getCharWidthAndCheckMonospace
=
(
char
:
string
):
number
=>
{
const
charWidth
=
getCharWidth
(
char
);
if
(
isMonospace
)
{
const
diff
=
typicalHalfwidthCharacter
-
charWidth
;
if
(
diff
<
-
0.001
||
diff
>
0.001
)
{
isMonospace
=
false
;
}
}
return
charWidth
;
};
let
checkMonospace
=
(
char
:
string
):
void
=>
{
if
(
isMonospace
)
{
const
charWidth
=
getCharWidth
(
char
);
const
diff
=
typicalHalfwidthCharacter
-
charWidth
;
if
(
diff
<
-
0.001
||
diff
>
0.001
)
{
isMonospace
=
false
;
}
let
referenceWidth
=
monospace
[
0
].
width
;
for
(
let
i
=
1
,
len
=
monospace
.
length
;
i
<
len
;
i
++
)
{
const
diff
=
referenceWidth
-
monospace
[
i
].
width
;
if
(
diff
<
-
0.001
||
diff
>
0.001
)
{
isMonospace
=
false
;
break
;
}
};
monospaceWidth
=
typicalHalfwidthCharacter
;
const
space
=
getCharWidthAndCheckMonospace
(
'
'
);
const
digit0
=
getCharWidthAndCheckMonospace
(
'
0
'
);
const
digit1
=
getCharWidthAndCheckMonospace
(
'
1
'
);
const
digit2
=
getCharWidthAndCheckMonospace
(
'
2
'
);
const
digit3
=
getCharWidthAndCheckMonospace
(
'
3
'
);
const
digit4
=
getCharWidthAndCheckMonospace
(
'
4
'
);
const
digit5
=
getCharWidthAndCheckMonospace
(
'
5
'
);
const
digit6
=
getCharWidthAndCheckMonospace
(
'
6
'
);
const
digit7
=
getCharWidthAndCheckMonospace
(
'
7
'
);
const
digit8
=
getCharWidthAndCheckMonospace
(
'
8
'
);
const
digit9
=
getCharWidthAndCheckMonospace
(
'
9
'
);
const
maxDigitWidth
=
Math
.
max
(
digit0
,
digit1
,
digit2
,
digit3
,
digit4
,
digit5
,
digit6
,
digit7
,
digit8
,
digit9
);
// monospace test: used for whitespace rendering
checkMonospace
(
'
→
'
);
checkMonospace
(
'
·
'
);
// monospace test: some characters
checkMonospace
(
'
|
'
);
checkMonospace
(
'
/
'
);
checkMonospace
(
'
-
'
);
checkMonospace
(
'
_
'
);
checkMonospace
(
'
i
'
);
checkMonospace
(
'
l
'
);
checkMonospace
(
'
m
'
);
context
.
font
=
`italic normal normal normal
${
bareFontInfo
.
fontSize
}
px /
${
bareFontInfo
.
lineHeight
}
px
${
bareFontInfo
.
fontFamily
}
`
;
checkMonospace
(
'
|
'
);
checkMonospace
(
'
_
'
);
checkMonospace
(
'
i
'
);
checkMonospace
(
'
l
'
);
checkMonospace
(
'
m
'
);
checkMonospace
(
'
n
'
);
context
.
font
=
`normal normal bold normal
${
bareFontInfo
.
fontSize
}
px /
${
bareFontInfo
.
lineHeight
}
px
${
bareFontInfo
.
fontFamily
}
`
;
checkMonospace
(
'
|
'
);
checkMonospace
(
'
_
'
);
checkMonospace
(
'
i
'
);
checkMonospace
(
'
l
'
);
checkMonospace
(
'
m
'
);
checkMonospace
(
'
n
'
);
}
return
new
FontInfo
({
fontFamily
:
bareFontInfo
.
fontFamily
,
...
...
@@ -211,9 +202,9 @@ class CSSBasedConfiguration extends Disposable {
fontSize
:
bareFontInfo
.
fontSize
,
lineHeight
:
bareFontInfo
.
lineHeight
,
isMonospace
:
isMonospace
,
typicalHalfwidthCharacterWidth
:
typicalHalfwidthCharacter
,
typicalFullwidthCharacterWidth
:
typicalFullwidthCharacter
,
spaceWidth
:
space
,
typicalHalfwidthCharacterWidth
:
typicalHalfwidthCharacter
.
width
,
typicalFullwidthCharacterWidth
:
typicalFullwidthCharacter
.
width
,
spaceWidth
:
space
.
width
,
maxDigitWidth
:
maxDigitWidth
});
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录