Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Obs Studio
提交
e1611b43
O
Obs Studio
项目概览
小白菜888
/
Obs Studio
通知
4
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
Obs Studio
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e1611b43
编写于
8月 17, 2014
作者:
P
paibox
提交者:
jp9000
8月 18, 2014
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Merge Freetype text plugin
上级
83fe23e1
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
1221 addition
and
0 deletion
+1221
-0
cmake/Modules/FindFreetype.cmake
cmake/Modules/FindFreetype.cmake
+56
-0
plugins/CMakeLists.txt
plugins/CMakeLists.txt
+1
-0
plugins/text-freetype2/CMakeLists.txt
plugins/text-freetype2/CMakeLists.txt
+23
-0
plugins/text-freetype2/data/locale/en-US.ini
plugins/text-freetype2/data/locale/en-US.ini
+12
-0
plugins/text-freetype2/data/text_default.effect
plugins/text-freetype2/data/text_default.effect
+56
-0
plugins/text-freetype2/obs-convenience.c
plugins/text-freetype2/obs-convenience.c
+84
-0
plugins/text-freetype2/obs-convenience.h
plugins/text-freetype2/obs-convenience.h
+43
-0
plugins/text-freetype2/text-freetype2.c
plugins/text-freetype2/text-freetype2.c
+399
-0
plugins/text-freetype2/text-freetype2.h
plugins/text-freetype2/text-freetype2.h
+90
-0
plugins/text-freetype2/text-functionality.c
plugins/text-freetype2/text-functionality.c
+457
-0
未找到文件。
cmake/Modules/FindFreetype.cmake
0 → 100644
浏览文件 @
e1611b43
# Once done these will be defined:
#
# LIBFREETYPE_FOUND
# LIBFREETYPE_INCLUDE_DIRS
# LIBFREETYPE_LIBRARIES
#
# For use in OBS:
#
# FREETYPE_INCLUDE_DIR
#
if
(
LIBFREETYPE_INCLUDE_DIRS AND LIBFREETYPE_LIBRARIES
)
set
(
LIBFREETYPE_FOUND TRUE
)
else
()
find_package
(
PkgConfig QUIET
)
if
(
PKG_CONFIG_FOUND
)
pkg_check_modules
(
_FREETYPE QUIET freetype2
)
endif
()
if
(
CMAKE_SIZEOF_VOID_P EQUAL 8
)
set
(
_lib_suffix 64
)
else
()
set
(
_lib_suffix 32
)
endif
()
set
(
FREETYPE_PATH_ARCH FreetypePath
${
_lib_suffix
}
)
find_path
(
FREETYPE_INCLUDE_DIR
NAMES ft2build.h
HINTS
${
_FREETYPE_INCLUDE_DIRS
}
"
${
CMAKE_SOURCE_DIR
}
/additional_install_files/include"
"$ENV{obsAdditionalInstallFiles}/include"
ENV FreetypePath
ENV
${
FREETYPE_PATH_ARCH
}
PATHS
/usr/include /usr/local/include /opt/local/include /sw/include
)
find_library
(
FREETYPE_LIB
NAMES
${
_FREETYPE_LIBRARIES
}
freetype libfreetype
HINTS
${
_FREETYPE_LIBRARY_DIRS
}
"
${
FREETYPE_INCLUDE_DIR
}
/../lib"
"
${
FREETYPE_INCLUDE_DIR
}
/../lib
${
_lib_suffix
}
"
"
${
FREETYPE_INCLUDE_DIR
}
/../libs
${
_lib_suffix
}
"
"
${
FREETYPE_INCLUDE_DIR
}
/lib"
"
${
FREETYPE_INCLUDE_DIR
}
/lib
${
_lib_suffix
}
"
PATHS
/usr/lib /usr/local/lib /opt/local/lib /sw/lib
)
set
(
LIBFREETYPE_INCLUDE_DIRS
${
FREETYPE_INCLUDE_DIR
}
CACHE PATH
"freetype include dir"
)
set
(
LIBFREETYPE_LIBRARIES
${
FREETYPE_LIB
}
CACHE STRING
"freetype libraries"
)
find_package_handle_standard_args
(
Libfreetype DEFAULT_MSG FREETYPE_LIB FREETYPE_INCLUDE_DIR
)
mark_as_advanced
(
FREETYPE_INCLUDE_DIR FREETYPE_LIB
)
endif
()
plugins/CMakeLists.txt
浏览文件 @
e1611b43
...
...
@@ -19,3 +19,4 @@ add_subdirectory(obs-libfdk)
add_subdirectory
(
obs-ffmpeg
)
add_subdirectory
(
obs-outputs
)
add_subdirectory
(
rtmp-services
)
add_subdirectory
(
text-freetype2
)
plugins/text-freetype2/CMakeLists.txt
0 → 100644
浏览文件 @
e1611b43
project
(
text-freetype2
)
find_package
(
Freetype REQUIRED
)
include_directories
(
SYSTEM
"
${
CMAKE_SOURCE_DIR
}
/libobs"
${
LIBFREETYPE_INCLUDE_DIRS
}
)
set
(
text-freetype2_SOURCES
obs-convenience.c
text-functionality.c
text-freetype2.c
obs-convenience.h
text-freetype2.h
)
add_library
(
text-freetype2 MODULE
${
text-freetype2_SOURCES
}
)
target_link_libraries
(
text-freetype2
libobs
${
LIBFREETYPE_LIBRARIES
}
)
install_obs_plugin
(
text-freetype2
)
install_obs_plugin_data
(
text-freetype2 data
)
plugins/text-freetype2/data/locale/en-US.ini
0 → 100644
浏览文件 @
e1611b43
FontFile
=
"Font File"
Text
=
"Text"
TextFile
=
"Text File (UTF-8 or UTF-16)"
ChatLogMode
=
"Chat log mode (last 6 lines)"
FontSize
=
"Font Size (Pixels)"
Color1
=
"Color 1"
Color2
=
"Color 2"
Outline
=
"Outline"
DropShadow
=
"Drop Shadow"
ReadFromFile
=
"Read from file"
CustomWidth
=
"Custom text width"
WordWrap
=
"Word Wrap"
\ No newline at end of file
plugins/text-freetype2/data/text_default.effect
0 → 100644
浏览文件 @
e1611b43
uniform float4x4 ViewProj;
uniform float4x4 color_matrix;
uniform float3 color_range_min = {0.0, 0.0, 0.0};
uniform float3 color_range_max = {1.0, 1.0, 1.0};
uniform texture2d image;
sampler_state def_sampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};
struct VertInOut {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float4 col : COLOR;
};
VertInOut VSDefault(VertInOut vert_in)
{
VertInOut vert_out;
vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
vert_out.uv = vert_in.uv;
vert_out.col = vert_in.col;
return vert_out;
}
float4 PSDrawBare(VertInOut vert_in) : TARGET
{
return image.Sample(def_sampler, vert_in.uv) * vert_in.col;
}
float4 PSDrawMatrix(VertInOut vert_in) : TARGET
{
float4 yuv = image.Sample(def_sampler, vert_in.uv);
yuv.xyz = clamp(yuv.xyz, color_range_min, color_range_max);
return saturate(mul(float4(yuv.xyz, 1.0), color_matrix));
}
technique Draw
{
pass
{
vertex_shader = VSDefault(vert_in);
pixel_shader = PSDrawBare(vert_in);
}
}
technique DrawMatrix
{
pass
{
vertex_shader = VSDefault(vert_in);
pixel_shader = PSDrawMatrix(vert_in);
}
}
plugins/text-freetype2/obs-convenience.c
0 → 100644
浏览文件 @
e1611b43
/******************************************************************************
Copyright (C) 2014 by Nibbles
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include <obs-module.h>
#include <graphics/vec2.h>
#include <graphics/vec3.h>
#include <graphics/vec4.h>
#include "obs-convenience.h"
gs_vertbuffer_t
create_uv_vbuffer
(
uint32_t
num_verts
,
bool
add_color
)
{
obs_enter_graphics
();
gs_vertbuffer_t
tmp
=
NULL
;
struct
gs_vb_data
*
vrect
=
NULL
;
vrect
=
gs_vbdata_create
();
vrect
->
num
=
num_verts
;
vrect
->
points
=
(
struct
vec3
*
)
bmalloc
(
sizeof
(
struct
vec3
)
*
num_verts
);
vrect
->
num_tex
=
1
;
vrect
->
tvarray
=
(
struct
gs_tvertarray
*
)
bmalloc
(
sizeof
(
struct
gs_tvertarray
));
vrect
->
tvarray
[
0
].
width
=
2
;
vrect
->
tvarray
[
0
].
array
=
bmalloc
(
sizeof
(
struct
vec2
)
*
num_verts
);
if
(
add_color
)
vrect
->
colors
=
(
uint32_t
*
)
bmalloc
(
sizeof
(
uint32_t
)
*
num_verts
);
memset
(
vrect
->
points
,
0
,
sizeof
(
struct
vec3
)
*
num_verts
);
memset
(
vrect
->
tvarray
[
0
].
array
,
0
,
sizeof
(
struct
vec2
)
*
num_verts
);
if
(
add_color
)
memset
(
vrect
->
colors
,
0
,
sizeof
(
uint32_t
)
*
num_verts
);
tmp
=
gs_vertexbuffer_create
(
vrect
,
GS_DYNAMIC
);
if
(
tmp
==
NULL
)
{
blog
(
LOG_WARNING
,
"Couldn't create UV vertex buffer."
);
}
obs_leave_graphics
();
return
tmp
;
}
void
draw_uv_vbuffer
(
gs_vertbuffer_t
vbuf
,
gs_texture_t
tex
,
gs_effect_t
effect
,
uint32_t
num_verts
)
{
gs_texture_t
texture
=
tex
;
gs_technique_t
tech
=
gs_effect_get_technique
(
effect
,
"Draw"
);
gs_eparam_t
image
=
gs_effect_get_param_by_name
(
effect
,
"image"
);
size_t
passes
;
if
(
vbuf
==
NULL
||
tex
==
NULL
)
return
;
gs_vertexbuffer_flush
(
vbuf
);
gs_load_vertexbuffer
(
vbuf
);
gs_load_indexbuffer
(
NULL
);
passes
=
gs_technique_begin
(
tech
);
for
(
size_t
i
=
0
;
i
<
passes
;
i
++
)
{
if
(
gs_technique_begin_pass
(
tech
,
i
))
{
gs_effect_set_texture
(
image
,
texture
);
gs_draw
(
GS_TRIS
,
0
,
num_verts
);
gs_technique_end_pass
(
tech
);
}
}
gs_technique_end
(
tech
);
}
plugins/text-freetype2/obs-convenience.h
0 → 100644
浏览文件 @
e1611b43
/******************************************************************************
Copyright (C) 2014 by Nibbles
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include <obs-module.h>
gs_vertbuffer_t
create_uv_vbuffer
(
uint32_t
num_verts
,
bool
add_color
);
void
draw_uv_vbuffer
(
gs_vertbuffer_t
vbuf
,
gs_texture_t
tex
,
gs_effect_t
effect
,
uint32_t
num_verts
);
#define set_v3_rect(a, x, y, w, h) \
vec3_set(a, x, y, 0.0f); \
vec3_set(a + 1, x + w, y, 0.0f); \
vec3_set(a + 2, x, y + h, 0.0f); \
vec3_set(a + 3, x, y + h, 0.0f); \
vec3_set(a + 4, x + w, y, 0.0f); \
vec3_set(a + 5, x + w, y + h, 0.0f);
#define set_v2_uv(a, u, v, u2, v2) \
vec2_set(a, u, v); \
vec2_set(a + 1, u2, v); \
vec2_set(a + 2, u, v2); \
vec2_set(a + 3, u, v2); \
vec2_set(a + 4, u2, v); \
vec2_set(a + 5, u2, v2);
#define set_rect_colors2(a, c1, c2) \
uint32_t *b = a; \
b[0] = b[1] = b[4] = c1; \
b[2] = b[3] = b[5] = c2;
plugins/text-freetype2/text-freetype2.c
0 → 100644
浏览文件 @
e1611b43
/******************************************************************************
Copyright (C) 2014 by Nibbles
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include <obs-module.h>
#include <util/platform.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <sys/stat.h>
#include "text-freetype2.h"
#include "obs-convenience.h"
FT_Library
ft2_lib
;
OBS_DECLARE_MODULE
()
OBS_MODULE_USE_DEFAULT_LOCALE
(
"text-freetype2"
,
"en-US"
)
uint32_t
texbuf_w
=
2048
,
texbuf_h
=
2048
;
static
struct
obs_source_info
freetype2_source_info
=
{
.
id
=
"text_ft2_source"
,
.
type
=
OBS_SOURCE_TYPE_INPUT
,
.
output_flags
=
OBS_SOURCE_VIDEO
,
.
get_name
=
ft2_source_get_name
,
.
create
=
ft2_source_create
,
.
destroy
=
ft2_source_destroy
,
.
update
=
ft2_source_update
,
.
get_width
=
ft2_source_get_width
,
.
get_height
=
ft2_source_get_height
,
.
video_render
=
ft2_source_render
,
.
video_tick
=
ft2_video_tick
,
.
get_properties
=
ft2_source_properties
,
};
bool
obs_module_load
()
{
FT_Init_FreeType
(
&
ft2_lib
);
if
(
ft2_lib
==
NULL
)
{
blog
(
LOG_WARNING
,
"FT2-text: Failed to initialize FT2."
);
return
false
;
}
obs_register_source
(
&
freetype2_source_info
);
return
true
;
}
void
obs_module_unload
(
void
)
{
FT_Done_FreeType
(
ft2_lib
);
}
static
const
char
*
ft2_source_get_name
(
void
)
{
return
obs_module_text
(
"Text (FreeType 2)"
);
}
static
uint32_t
ft2_source_get_width
(
void
*
data
)
{
struct
ft2_source
*
srcdata
=
data
;
return
srcdata
->
cx
;
}
static
uint32_t
ft2_source_get_height
(
void
*
data
)
{
struct
ft2_source
*
srcdata
=
data
;
return
srcdata
->
cy
;
}
static
obs_properties_t
ft2_source_properties
(
void
)
{
obs_properties_t
props
=
obs_properties_create
();
//obs_property_t prop;
// TODO:
// Get system fonts, no idea how.
// Scrolling. Can't think of a way to do it with the render
// targets currently being broken. (0.4.2)
// Better/pixel shader outline/drop shadow
// Some way to pull text files from network, I dunno
obs_properties_add_path
(
props
,
"font_file"
,
obs_module_text
(
"FontFile"
),
OBS_PATH_FILE
,
"All font formats (*.ttf *.otf);;"
,
NULL
);
obs_properties_add_text
(
props
,
"text"
,
obs_module_text
(
"Text"
),
OBS_TEXT_MULTILINE
);
obs_properties_add_bool
(
props
,
"from_file"
,
obs_module_text
(
"ReadFromFile"
));
obs_properties_add_bool
(
props
,
"log_mode"
,
obs_module_text
(
"ChatLogMode"
));
obs_properties_add_path
(
props
,
"text_file"
,
obs_module_text
(
"TextFile"
),
OBS_PATH_FILE
,
"All font formats (*.txt);;"
,
NULL
);
obs_properties_add_int
(
props
,
"font_size"
,
obs_module_text
(
"FontSize"
),
0
,
72
,
1
);
obs_properties_add_color
(
props
,
"color1"
,
obs_module_text
(
"Color1"
));
obs_properties_add_color
(
props
,
"color2"
,
obs_module_text
(
"Color2"
));
obs_properties_add_bool
(
props
,
"outline"
,
obs_module_text
(
"Outline"
));
obs_properties_add_bool
(
props
,
"drop_shadow"
,
obs_module_text
(
"DropShadow"
));
obs_properties_add_int
(
props
,
"custom_width"
,
obs_module_text
(
"CustomWidth"
),
0
,
4096
,
1
);
obs_properties_add_bool
(
props
,
"word_wrap"
,
obs_module_text
(
"WordWrap"
));
return
props
;
}
static
void
ft2_source_destroy
(
void
*
data
)
{
struct
ft2_source
*
srcdata
=
data
;
if
(
srcdata
->
font_face
!=
NULL
)
{
FT_Done_Face
(
srcdata
->
font_face
);
srcdata
->
font_face
=
NULL
;
}
for
(
uint32_t
i
=
0
;
i
<
num_cache_slots
;
i
++
)
{
if
(
srcdata
->
cacheglyphs
[
i
]
!=
NULL
)
{
bfree
(
srcdata
->
cacheglyphs
[
i
]);
srcdata
->
cacheglyphs
[
i
]
=
NULL
;
}
}
if
(
srcdata
->
font_name
!=
NULL
)
bfree
(
srcdata
->
font_name
);
if
(
srcdata
->
text
!=
NULL
)
bfree
(
srcdata
->
text
);
if
(
srcdata
->
texbuf
!=
NULL
)
bfree
(
srcdata
->
texbuf
);
if
(
srcdata
->
colorbuf
!=
NULL
)
bfree
(
srcdata
->
colorbuf
);
if
(
srcdata
->
text_file
!=
NULL
)
bfree
(
srcdata
->
text_file
);
obs_enter_graphics
();
if
(
srcdata
->
tex
!=
NULL
)
{
gs_texture_destroy
(
srcdata
->
tex
);
srcdata
->
tex
=
NULL
;
}
if
(
srcdata
->
vbuf
!=
NULL
)
{
gs_vertexbuffer_destroy
(
srcdata
->
vbuf
);
srcdata
->
vbuf
=
NULL
;
}
if
(
srcdata
->
draw_effect
!=
NULL
)
{
gs_effect_destroy
(
srcdata
->
draw_effect
);
srcdata
->
draw_effect
=
NULL
;
}
obs_leave_graphics
();
bfree
(
srcdata
);
}
static
void
ft2_source_render
(
void
*
data
,
gs_effect_t
effect
)
{
struct
ft2_source
*
srcdata
=
data
;
if
(
srcdata
==
NULL
)
return
;
if
(
srcdata
->
tex
==
NULL
||
srcdata
->
vbuf
==
NULL
)
return
;
gs_reset_blend_state
();
if
(
srcdata
->
outline_text
)
draw_outlines
(
srcdata
);
if
(
srcdata
->
drop_shadow
)
draw_drop_shadow
(
srcdata
);
draw_uv_vbuffer
(
srcdata
->
vbuf
,
srcdata
->
tex
,
srcdata
->
draw_effect
,
(
uint32_t
)
wcslen
(
srcdata
->
text
)
*
6
);
UNUSED_PARAMETER
(
effect
);
}
static
void
ft2_video_tick
(
void
*
data
,
float
seconds
)
{
struct
ft2_source
*
srcdata
=
data
;
if
(
srcdata
==
NULL
)
return
;
if
(
srcdata
->
text_file
==
NULL
)
return
;
if
(
os_gettime_ns
()
-
srcdata
->
last_checked
>=
1000000000
)
{
srcdata
->
last_checked
=
os_gettime_ns
();
if
(
srcdata
->
m_timestamp
!=
get_modified_timestamp
(
srcdata
->
text_file
))
{
if
(
srcdata
->
log_mode
)
read_from_end
(
srcdata
,
srcdata
->
text_file
);
else
load_text_from_file
(
srcdata
,
srcdata
->
text_file
);
set_up_vertex_buffer
(
srcdata
);
}
}
UNUSED_PARAMETER
(
seconds
);
}
static
void
ft2_source_update
(
void
*
data
,
obs_data_t
settings
)
{
struct
ft2_source
*
srcdata
=
data
;
const
char
*
tmp
=
obs_data_get_string
(
settings
,
"font_file"
);
bool
vbuf_needs_update
=
false
;
bool
word_wrap
=
false
;
uint32_t
color
[
2
];
uint32_t
custom_width
=
0
;
srcdata
->
drop_shadow
=
obs_data_get_bool
(
settings
,
"drop_shadow"
);
srcdata
->
outline_text
=
obs_data_get_bool
(
settings
,
"outline"
);
word_wrap
=
obs_data_get_bool
(
settings
,
"word_wrap"
);
color
[
0
]
=
(
uint32_t
)
obs_data_get_int
(
settings
,
"color1"
);
color
[
1
]
=
(
uint32_t
)
obs_data_get_int
(
settings
,
"color2"
);
custom_width
=
(
uint32_t
)
obs_data_get_int
(
settings
,
"custom_width"
);
if
(
custom_width
>=
100
)
{
if
(
custom_width
!=
srcdata
->
custom_width
)
{
srcdata
->
custom_width
=
custom_width
;
vbuf_needs_update
=
true
;
}
}
else
{
if
(
srcdata
->
custom_width
>=
100
)
vbuf_needs_update
=
true
;
srcdata
->
custom_width
=
0
;
}
if
(
word_wrap
!=
srcdata
->
word_wrap
)
{
srcdata
->
word_wrap
=
word_wrap
;
vbuf_needs_update
=
true
;
}
if
(
color
[
0
]
!=
srcdata
->
color
[
0
]
||
color
[
1
]
!=
srcdata
->
color
[
1
])
{
srcdata
->
color
[
0
]
=
color
[
0
];
srcdata
->
color
[
1
]
=
color
[
1
];
vbuf_needs_update
=
true
;
}
bool
from_file
=
obs_data_get_bool
(
settings
,
"from_file"
);
bool
chat_log_mode
=
obs_data_get_bool
(
settings
,
"log_mode"
);
srcdata
->
log_mode
=
chat_log_mode
;
if
(
ft2_lib
==
NULL
)
return
;
if
(
!
from_file
)
{
if
(
srcdata
->
text_file
!=
NULL
)
{
bfree
(
srcdata
->
text_file
);
srcdata
->
text_file
=
NULL
;
}
}
if
(
srcdata
->
draw_effect
==
NULL
)
{
char
*
effect_file
=
NULL
;
char
*
error_string
=
NULL
;
effect_file
=
obs_module_file
(
"text_default.effect"
);
if
(
effect_file
)
{
obs_enter_graphics
();
srcdata
->
draw_effect
=
gs_effect_create_from_file
(
effect_file
,
&
error_string
);
obs_leave_graphics
();
bfree
(
effect_file
);
if
(
error_string
!=
NULL
)
bfree
(
error_string
);
}
}
if
(
srcdata
->
font_size
!=
obs_data_get_int
(
settings
,
"font_size"
))
vbuf_needs_update
=
true
;
if
(
srcdata
->
font_name
!=
NULL
)
{
if
(
strcmp
(
tmp
,
srcdata
->
font_name
)
==
0
&&
srcdata
->
font_size
==
obs_data_get_int
(
settings
,
"font_size"
))
goto
skip_font_load
;
bfree
(
srcdata
->
font_name
);
srcdata
->
font_name
=
NULL
;
srcdata
->
max_h
=
0
;
}
srcdata
->
font_name
=
bzalloc
(
strlen
(
tmp
)
+
1
);
strcpy
(
srcdata
->
font_name
,
tmp
);
if
(
srcdata
->
font_face
!=
NULL
)
{
FT_Done_Face
(
srcdata
->
font_face
);
srcdata
->
font_face
=
NULL
;
}
FT_New_Face
(
ft2_lib
,
srcdata
->
font_name
,
0
,
&
srcdata
->
font_face
);
if
(
srcdata
->
font_face
==
NULL
)
{
blog
(
LOG_WARNING
,
"FT2-text: Failed to load font %s"
,
srcdata
->
font_name
);
return
;
}
else
{
srcdata
->
font_size
=
(
uint16_t
)
obs_data_get_int
(
settings
,
"font_size"
);
FT_Set_Pixel_Sizes
(
srcdata
->
font_face
,
0
,
srcdata
->
font_size
);
FT_Select_Charmap
(
srcdata
->
font_face
,
FT_ENCODING_UNICODE
);
}
if
(
srcdata
->
texbuf
!=
NULL
)
{
bfree
(
srcdata
->
texbuf
);
srcdata
->
texbuf
=
NULL
;
}
srcdata
->
texbuf
=
bzalloc
(
texbuf_w
*
texbuf_h
*
4
);
cache_standard_glyphs
(
srcdata
);
skip_font_load:
;
if
(
from_file
)
{
tmp
=
obs_data_get_string
(
settings
,
"text_file"
);
if
(
strlen
(
tmp
)
==
0
)
return
;
if
(
srcdata
->
text_file
!=
NULL
)
{
if
(
strcmp
(
srcdata
->
text_file
,
tmp
)
==
0
&&
!
vbuf_needs_update
)
return
;
bfree
(
srcdata
->
text_file
);
srcdata
->
text_file
=
NULL
;
}
else
blog
(
LOG_WARNING
,
"FT2-text: Failed to open %s for reading"
,
tmp
);
srcdata
->
text_file
=
bzalloc
(
strlen
(
tmp
)
+
1
);
strcpy
(
srcdata
->
text_file
,
tmp
);
if
(
chat_log_mode
)
read_from_end
(
srcdata
,
tmp
);
else
load_text_from_file
(
srcdata
,
tmp
);
srcdata
->
last_checked
=
os_gettime_ns
();
}
else
{
tmp
=
obs_data_get_string
(
settings
,
"text"
);
if
(
strlen
(
tmp
)
==
0
)
return
;
if
(
srcdata
->
text
!=
NULL
)
{
bfree
(
srcdata
->
text
);
srcdata
->
text
=
NULL
;
}
srcdata
->
text
=
bzalloc
((
strlen
(
tmp
)
+
1
)
*
sizeof
(
wchar_t
));
os_utf8_to_wcs
(
tmp
,
strlen
(
tmp
),
srcdata
->
text
,
(
strlen
(
tmp
)
+
1
));
}
cache_glyphs
(
srcdata
,
srcdata
->
text
);
set_up_vertex_buffer
(
srcdata
);
}
static
void
*
ft2_source_create
(
obs_data_t
settings
,
obs_source_t
source
)
{
struct
ft2_source
*
srcdata
=
bzalloc
(
sizeof
(
struct
ft2_source
));
srcdata
->
src
=
source
;
srcdata
->
font_size
=
32
;
obs_data_set_default_int
(
settings
,
"font_size"
,
32
);
obs_data_set_default_int
(
settings
,
"color1"
,
0xFFFFFFFF
);
obs_data_set_default_int
(
settings
,
"color2"
,
0xFFFFFFFF
);
obs_data_set_default_string
(
settings
,
"text"
,
"The lazy snake jumps over the happy MASKEN."
);
ft2_source_update
(
srcdata
,
settings
);
return
srcdata
;
}
plugins/text-freetype2/text-freetype2.h
0 → 100644
浏览文件 @
e1611b43
/******************************************************************************
Copyright (C) 2014 by Nibbles
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include <obs-module.h>
#include <ft2build.h>
#define num_cache_slots 65535
#define src_glyph srcdata->cacheglyphs[glyph_index]
struct
glyph_info
{
float
u
,
v
,
u2
,
v2
;
int32_t
w
,
h
,
xoff
,
yoff
;
int32_t
xadv
;
};
struct
ft2_source
{
uint8_t
font_type
;
char
*
font_name
;
char
*
text_file
;
wchar_t
*
text
;
uint16_t
font_size
;
time_t
m_timestamp
;
uint64_t
last_checked
;
uint32_t
cx
,
cy
,
max_h
,
custom_width
;
uint32_t
texbuf_x
,
texbuf_y
;
uint32_t
color
[
2
];
uint32_t
*
colorbuf
;
int32_t
cur_scroll
,
scroll_speed
;
gs_texture_t
tex
;
struct
glyph_info
*
cacheglyphs
[
num_cache_slots
];
FT_Face
font_face
;
uint32_t
*
texbuf
;
gs_vertbuffer_t
vbuf
;
gs_effect_t
draw_effect
;
bool
outline_text
,
drop_shadow
;
bool
log_mode
,
word_wrap
;
obs_source_t
src
;
};
extern
FT_Library
ft2_lib
;
static
void
*
ft2_source_create
(
obs_data_t
settings
,
obs_source_t
source
);
static
void
ft2_source_destroy
(
void
*
data
);
static
void
ft2_source_update
(
void
*
data
,
obs_data_t
settings
);
static
void
ft2_source_render
(
void
*
data
,
gs_effect_t
effect
);
static
void
ft2_video_tick
(
void
*
data
,
float
seconds
);
void
draw_outlines
(
struct
ft2_source
*
srcdata
);
void
draw_drop_shadow
(
struct
ft2_source
*
srcdata
);
static
uint32_t
ft2_source_get_width
(
void
*
data
);
static
uint32_t
ft2_source_get_height
(
void
*
data
);
static
obs_properties_t
ft2_source_properties
(
void
);
static
const
char
*
ft2_source_get_name
(
void
);
uint32_t
get_ft2_text_width
(
wchar_t
*
text
,
struct
ft2_source
*
srcdata
);
time_t
get_modified_timestamp
(
char
*
filename
);
void
load_text_from_file
(
struct
ft2_source
*
srcdata
,
const
char
*
filename
);
void
read_from_end
(
struct
ft2_source
*
srcdata
,
const
char
*
filename
);
void
cache_standard_glyphs
(
struct
ft2_source
*
srcdata
);
void
cache_glyphs
(
struct
ft2_source
*
srcdata
,
wchar_t
*
cache_glyphs
);
void
set_up_vertex_buffer
(
struct
ft2_source
*
srcdata
);
void
fill_vertex_buffer
(
struct
ft2_source
*
srcdata
);
plugins/text-freetype2/text-functionality.c
0 → 100644
浏览文件 @
e1611b43
/******************************************************************************
Copyright (C) 2014 by Nibbles
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include <obs-module.h>
#include <util/platform.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <sys/stat.h>
#include "text-freetype2.h"
#include "obs-convenience.h"
float
offsets
[
16
]
=
{
-
2
.
0
f
,
0
.
0
f
,
0
.
0
f
,
-
2
.
0
f
,
2
.
0
f
,
0
.
0
f
,
2
.
0
f
,
0
.
0
f
,
0
.
0
f
,
2
.
0
f
,
0
.
0
f
,
2
.
0
f
,
-
2
.
0
f
,
0
.
0
f
,
-
2
.
0
f
,
0
.
0
f
};
extern
uint32_t
texbuf_w
,
texbuf_h
;
void
draw_outlines
(
struct
ft2_source
*
srcdata
)
{
// Horrible (hopefully temporary) solution for outlines.
uint32_t
*
tmp
;
struct
gs_vb_data
*
vdata
=
gs_vertexbuffer_get_data
(
srcdata
->
vbuf
);
tmp
=
vdata
->
colors
;
vdata
->
colors
=
srcdata
->
colorbuf
;
gs_matrix_push
();
for
(
int32_t
i
=
0
;
i
<
8
;
i
++
)
{
gs_matrix_translate3f
(
offsets
[
i
*
2
],
offsets
[(
i
*
2
)
+
1
],
0
.
0
f
);
draw_uv_vbuffer
(
srcdata
->
vbuf
,
srcdata
->
tex
,
srcdata
->
draw_effect
,
(
uint32_t
)
wcslen
(
srcdata
->
text
)
*
6
);
}
gs_matrix_identity
();
gs_matrix_pop
();
vdata
->
colors
=
tmp
;
}
void
draw_drop_shadow
(
struct
ft2_source
*
srcdata
)
{
// Horrible (hopefully temporary) solution for drop shadow.
uint32_t
*
tmp
;
struct
gs_vb_data
*
vdata
=
gs_vertexbuffer_get_data
(
srcdata
->
vbuf
);
tmp
=
vdata
->
colors
;
vdata
->
colors
=
srcdata
->
colorbuf
;
gs_matrix_push
();
gs_matrix_translate3f
(
4
.
0
f
,
4
.
0
f
,
0
.
0
f
);
draw_uv_vbuffer
(
srcdata
->
vbuf
,
srcdata
->
tex
,
srcdata
->
draw_effect
,
(
uint32_t
)
wcslen
(
srcdata
->
text
)
*
6
);
gs_matrix_identity
();
gs_matrix_pop
();
vdata
->
colors
=
tmp
;
}
void
set_up_vertex_buffer
(
struct
ft2_source
*
srcdata
)
{
FT_UInt
glyph_index
=
0
;
uint32_t
x
=
0
,
space_pos
=
0
,
word_width
=
0
;
if
(
srcdata
->
custom_width
>=
100
)
srcdata
->
cx
=
srcdata
->
custom_width
;
else
srcdata
->
cx
=
get_ft2_text_width
(
srcdata
->
text
,
srcdata
);
srcdata
->
cy
=
srcdata
->
max_h
;
obs_enter_graphics
();
if
(
srcdata
->
vbuf
!=
NULL
)
{
gs_vertbuffer_t
tmpvbuf
=
srcdata
->
vbuf
;
srcdata
->
vbuf
=
NULL
;
gs_vertexbuffer_destroy
(
tmpvbuf
);
}
srcdata
->
vbuf
=
create_uv_vbuffer
((
uint32_t
)
wcslen
(
srcdata
->
text
)
*
6
,
true
);
if
(
srcdata
->
custom_width
<=
100
)
goto
skip_word_wrap
;
if
(
!
srcdata
->
word_wrap
)
goto
skip_word_wrap
;
for
(
uint32_t
i
=
0
;
i
<=
wcslen
(
srcdata
->
text
);
i
++
)
{
if
(
i
==
wcslen
(
srcdata
->
text
))
goto
eos_check
;
if
(
srcdata
->
text
[
i
]
!=
L' '
&&
srcdata
->
text
[
i
]
!=
L'\n'
)
goto
next_char
;
eos_check:
;
if
(
x
+
word_width
>
srcdata
->
custom_width
)
{
if
(
space_pos
!=
0
)
srcdata
->
text
[
space_pos
]
=
L'\n'
;
x
=
0
;
}
if
(
i
==
wcslen
(
srcdata
->
text
))
goto
eos_skip
;
x
+=
word_width
;
word_width
=
0
;
if
(
srcdata
->
text
[
i
]
==
L'\n'
)
x
=
0
;
if
(
srcdata
->
text
[
i
]
==
L' '
)
space_pos
=
i
;
next_char:
;
glyph_index
=
FT_Get_Char_Index
(
srcdata
->
font_face
,
srcdata
->
text
[
i
]);
word_width
+=
src_glyph
->
xadv
;
eos_skip:
;
}
skip_word_wrap:
;
fill_vertex_buffer
(
srcdata
);
obs_leave_graphics
();
}
void
fill_vertex_buffer
(
struct
ft2_source
*
srcdata
)
{
struct
gs_vb_data
*
vdata
=
gs_vertexbuffer_get_data
(
srcdata
->
vbuf
);
if
(
vdata
==
NULL
)
return
;
struct
vec2
*
tvarray
=
(
struct
vec2
*
)
vdata
->
tvarray
[
0
].
array
;
uint32_t
*
col
=
(
uint32_t
*
)
vdata
->
colors
;
FT_UInt
glyph_index
=
0
;
uint32_t
dx
=
0
,
dy
=
srcdata
->
max_h
,
max_y
=
dy
;
uint32_t
cur_glyph
=
0
;
if
(
srcdata
->
colorbuf
!=
NULL
)
{
bfree
(
srcdata
->
colorbuf
);
srcdata
->
colorbuf
=
NULL
;
}
srcdata
->
colorbuf
=
bzalloc
(
sizeof
(
uint32_t
)
*
wcslen
(
srcdata
->
text
)
*
6
);
for
(
uint32_t
i
=
0
;
i
<
wcslen
(
srcdata
->
text
)
*
6
;
i
++
)
{
srcdata
->
colorbuf
[
i
]
=
0xFF000000
;
}
for
(
uint32_t
i
=
0
;
i
<
wcslen
(
srcdata
->
text
);
i
++
)
{
add_linebreak:
;
if
(
srcdata
->
text
[
i
]
!=
L'\n'
)
goto
draw_glyph
;
dx
=
0
;
i
++
;
dy
+=
srcdata
->
max_h
+
4
;
if
(
i
==
wcslen
(
srcdata
->
text
))
goto
skip_glyph
;
if
(
srcdata
->
text
[
i
]
==
L'\n'
)
goto
add_linebreak
;
draw_glyph:
;
// Skip filthy dual byte Windows line breaks
if
(
srcdata
->
text
[
i
]
==
L'\r'
)
goto
skip_glyph
;
glyph_index
=
FT_Get_Char_Index
(
srcdata
->
font_face
,
srcdata
->
text
[
i
]);
if
(
src_glyph
==
NULL
)
goto
skip_glyph
;
if
(
srcdata
->
custom_width
<
100
)
goto
skip_custom_width
;
if
(
dx
+
src_glyph
->
xadv
>
srcdata
->
custom_width
)
{
dx
=
0
;
dy
+=
srcdata
->
max_h
+
4
;
}
skip_custom_width:
;
set_v3_rect
(
vdata
->
points
+
(
cur_glyph
*
6
),
(
float
)
dx
+
(
float
)
src_glyph
->
xoff
,
(
float
)
dy
-
(
float
)
src_glyph
->
yoff
,
(
float
)
src_glyph
->
w
,
(
float
)
src_glyph
->
h
);
set_v2_uv
(
tvarray
+
(
cur_glyph
*
6
),
src_glyph
->
u
,
src_glyph
->
v
,
src_glyph
->
u2
,
src_glyph
->
v2
);
set_rect_colors2
(
col
+
(
cur_glyph
*
6
),
srcdata
->
color
[
0
],
srcdata
->
color
[
1
]);
dx
+=
src_glyph
->
xadv
;
if
(
dy
-
(
float
)
src_glyph
->
yoff
+
src_glyph
->
h
>
max_y
)
max_y
=
dy
-
src_glyph
->
yoff
+
src_glyph
->
h
;
cur_glyph
++
;
skip_glyph:
;
}
srcdata
->
cy
=
max_y
;
}
void
cache_standard_glyphs
(
struct
ft2_source
*
srcdata
)
{
for
(
uint32_t
i
=
0
;
i
<
num_cache_slots
;
i
++
)
{
if
(
srcdata
->
cacheglyphs
[
i
]
!=
NULL
)
{
bfree
(
srcdata
->
cacheglyphs
[
i
]);
srcdata
->
cacheglyphs
[
i
]
=
NULL
;
}
}
srcdata
->
texbuf_x
=
0
;
srcdata
->
texbuf_y
=
0
;
cache_glyphs
(
srcdata
,
L"abcdefghijklmnopqrstuvwxyz"
\
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
\
L"!@#$%^&*()-_=+,<.>/?
\\
|[]{}`~
\'\"\0
"
);
}
#define glyph_pos x + (y*slot->bitmap.pitch)
#define buf_pos (dx + x) + ((dy + y) * texbuf_w)
void
cache_glyphs
(
struct
ft2_source
*
srcdata
,
wchar_t
*
cache_glyphs
)
{
FT_GlyphSlot
slot
=
srcdata
->
font_face
->
glyph
;
FT_UInt
glyph_index
=
0
;
uint32_t
dx
=
srcdata
->
texbuf_x
,
dy
=
srcdata
->
texbuf_y
;
uint8_t
alpha
;
int32_t
g_pitch
=
0
;
int32_t
cached_glyphs
=
0
;
for
(
uint32_t
i
=
0
;
i
<
wcslen
(
cache_glyphs
);
i
++
)
{
glyph_index
=
FT_Get_Char_Index
(
srcdata
->
font_face
,
cache_glyphs
[
i
]);
if
(
src_glyph
!=
NULL
)
goto
skip_glyph
;
FT_Load_Glyph
(
srcdata
->
font_face
,
glyph_index
,
FT_LOAD_DEFAULT
);
FT_Render_Glyph
(
slot
,
FT_RENDER_MODE_NORMAL
);
uint32_t
g_w
=
slot
->
bitmap
.
width
;
uint32_t
g_h
=
slot
->
bitmap
.
rows
;
g_pitch
=
slot
->
bitmap
.
pitch
;
if
(
srcdata
->
max_h
<
g_h
)
srcdata
->
max_h
=
g_h
;
if
(
dx
+
g_w
>=
texbuf_w
)
{
dx
=
0
;
dy
+=
srcdata
->
max_h
+
1
;
}
src_glyph
=
bzalloc
(
sizeof
(
struct
glyph_info
));
src_glyph
->
u
=
(
float
)
dx
/
(
float
)
texbuf_w
;
src_glyph
->
u2
=
(
float
)(
dx
+
g_w
)
/
(
float
)
texbuf_w
;
src_glyph
->
v
=
(
float
)
dy
/
(
float
)
texbuf_h
;
src_glyph
->
v2
=
(
float
)(
dy
+
g_h
)
/
(
float
)
texbuf_h
;
src_glyph
->
w
=
g_w
;
src_glyph
->
h
=
g_h
;
src_glyph
->
yoff
=
slot
->
bitmap_top
;
src_glyph
->
xoff
=
slot
->
bitmap_left
;
src_glyph
->
xadv
=
slot
->
advance
.
x
>>
6
;
for
(
uint32_t
y
=
0
;
y
<
g_h
;
y
++
)
{
for
(
uint32_t
x
=
0
;
x
<
g_w
;
x
++
)
{
alpha
=
slot
->
bitmap
.
buffer
[
glyph_pos
];
srcdata
->
texbuf
[
buf_pos
]
=
0x00FFFFFF
^
(
alpha
<<
24
);
}
}
dx
+=
(
g_w
+
1
);
if
(
dx
>=
texbuf_w
)
{
dx
=
0
;
dy
+=
srcdata
->
max_h
;
}
cached_glyphs
++
;
skip_glyph:
;
}
srcdata
->
texbuf_x
=
dx
;
srcdata
->
texbuf_y
=
dy
;
if
(
cached_glyphs
>
0
)
{
obs_enter_graphics
();
if
(
srcdata
->
tex
!=
NULL
)
{
gs_texture_t
tmp_texture
=
NULL
;
tmp_texture
=
srcdata
->
tex
;
srcdata
->
tex
=
NULL
;
gs_texture_destroy
(
tmp_texture
);
}
srcdata
->
tex
=
gs_texture_create
(
texbuf_w
,
texbuf_h
,
GS_RGBA
,
1
,
(
const
uint8_t
**
)
&
srcdata
->
texbuf
,
0
);
obs_leave_graphics
();
}
}
time_t
get_modified_timestamp
(
char
*
filename
)
{
struct
stat
stats
;
// stat is apparently terrifying and horrible, but we only call it once
// every second at most.
stat
(
filename
,
&
stats
);
return
stats
.
st_mtime
;
}
void
load_text_from_file
(
struct
ft2_source
*
srcdata
,
const
char
*
filename
)
{
FILE
*
tmp_file
=
NULL
;
uint32_t
filesize
=
0
;
char
*
tmp_read
=
NULL
;
uint16_t
header
=
0
;
tmp_file
=
fopen
(
filename
,
"rb"
);
if
(
tmp_file
==
NULL
)
{
blog
(
LOG_WARNING
,
"Failed to open file %s"
,
filename
);
return
;
}
fseek
(
tmp_file
,
0
,
SEEK_END
);
filesize
=
(
uint32_t
)
ftell
(
tmp_file
);
fseek
(
tmp_file
,
0
,
SEEK_SET
);
fread
(
&
header
,
2
,
1
,
tmp_file
);
if
(
header
==
0xFEFF
)
{
// File is already in UTF-16 format
if
(
srcdata
->
text
!=
NULL
)
{
bfree
(
srcdata
->
text
);
srcdata
->
text
=
NULL
;
}
srcdata
->
text
=
bzalloc
(
filesize
);
fread
(
srcdata
->
text
,
filesize
-
2
,
1
,
tmp_file
);
srcdata
->
m_timestamp
=
get_modified_timestamp
(
srcdata
->
text_file
);
bfree
(
tmp_read
);
fclose
(
tmp_file
);
return
;
}
fseek
(
tmp_file
,
0
,
SEEK_SET
);
srcdata
->
m_timestamp
=
get_modified_timestamp
(
srcdata
->
text_file
);
tmp_read
=
bzalloc
(
filesize
+
1
);
fread
(
tmp_read
,
filesize
,
1
,
tmp_file
);
fclose
(
tmp_file
);
if
(
srcdata
->
text
!=
NULL
)
{
bfree
(
srcdata
->
text
);
srcdata
->
text
=
NULL
;
}
srcdata
->
text
=
bzalloc
((
strlen
(
tmp_read
)
+
1
)
*
sizeof
(
wchar_t
));
os_utf8_to_wcs
(
tmp_read
,
strlen
(
tmp_read
),
srcdata
->
text
,
(
strlen
(
tmp_read
)
+
1
));
bfree
(
tmp_read
);
}
void
read_from_end
(
struct
ft2_source
*
srcdata
,
const
char
*
filename
)
{
FILE
*
tmp_file
=
NULL
;
uint32_t
filesize
=
0
,
cur_pos
=
0
;
char
*
tmp_read
=
NULL
;
uint16_t
value
=
0
,
line_breaks
=
0
;
char
bvalue
;
bool
utf16
=
false
;
tmp_file
=
fopen
(
filename
,
"rb"
);
if
(
tmp_file
==
NULL
)
{
blog
(
LOG_WARNING
,
"Failed to open file %s"
,
filename
);
return
;
}
fread
(
&
value
,
2
,
1
,
tmp_file
);
if
(
value
==
0xFEFF
)
utf16
=
true
;
fseek
(
tmp_file
,
0
,
SEEK_END
);
filesize
=
(
uint32_t
)
ftell
(
tmp_file
);
cur_pos
=
filesize
;
while
(
line_breaks
<=
6
&&
cur_pos
!=
0
)
{
if
(
!
utf16
)
cur_pos
--
;
else
cur_pos
-=
2
;
fseek
(
tmp_file
,
cur_pos
,
SEEK_SET
);
if
(
!
utf16
)
{
fread
(
&
bvalue
,
1
,
1
,
tmp_file
);
if
(
bvalue
==
'\n'
)
line_breaks
++
;
}
else
{
fread
(
&
value
,
2
,
1
,
tmp_file
);
if
(
value
==
L'\n'
)
line_breaks
++
;
}
}
if
(
cur_pos
!=
0
)
cur_pos
+=
(
utf16
)
?
2
:
1
;
fseek
(
tmp_file
,
cur_pos
,
SEEK_SET
);
if
(
utf16
)
{
if
(
srcdata
->
text
!=
NULL
)
{
bfree
(
srcdata
->
text
);
srcdata
->
text
=
NULL
;
}
srcdata
->
text
=
bzalloc
(
filesize
-
cur_pos
);
fread
(
srcdata
->
text
,
(
filesize
-
cur_pos
),
1
,
tmp_file
);
srcdata
->
m_timestamp
=
get_modified_timestamp
(
srcdata
->
text_file
);
bfree
(
tmp_read
);
fclose
(
tmp_file
);
return
;
}
tmp_read
=
bzalloc
((
filesize
-
cur_pos
)
+
1
);
fread
(
tmp_read
,
filesize
-
cur_pos
,
1
,
tmp_file
);
fclose
(
tmp_file
);
if
(
srcdata
->
text
!=
NULL
)
{
bfree
(
srcdata
->
text
);
srcdata
->
text
=
NULL
;
}
srcdata
->
text
=
bzalloc
((
strlen
(
tmp_read
)
+
1
)
*
sizeof
(
wchar_t
));
os_utf8_to_wcs
(
tmp_read
,
strlen
(
tmp_read
),
srcdata
->
text
,
(
strlen
(
tmp_read
)
+
1
));
srcdata
->
m_timestamp
=
get_modified_timestamp
(
srcdata
->
text_file
);
bfree
(
tmp_read
);
}
uint32_t
get_ft2_text_width
(
wchar_t
*
text
,
struct
ft2_source
*
srcdata
)
{
FT_GlyphSlot
slot
=
srcdata
->
font_face
->
glyph
;
FT_UInt
glyph_index
=
0
;
uint32_t
w
=
0
,
max_w
=
0
;
for
(
uint32_t
i
=
0
;
i
<
(
uint32_t
)
wcslen
(
text
);
i
++
)
{
glyph_index
=
FT_Get_Char_Index
(
srcdata
->
font_face
,
text
[
i
]);
FT_Load_Glyph
(
srcdata
->
font_face
,
glyph_index
,
FT_LOAD_DEFAULT
);
if
(
text
[
i
]
==
L'\n'
)
w
=
0
;
else
{
w
+=
slot
->
advance
.
x
>>
6
;
if
(
w
>
max_w
)
max_w
=
w
;
}
}
return
max_w
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录