├── .clang-format
├── .github
└── workflows
│ └── c.yml
├── .gitignore
├── LICENSE
├── README.md
├── contrib
└── systemd
│ ├── sov.service
│ └── sov.socket
├── meson.build
├── res
└── html
│ ├── main.css
│ └── main.html
├── screenshot.png
├── src
├── kinetic_ui
│ ├── egl
│ │ ├── ku_gl.c
│ │ ├── ku_gl_atlas.c
│ │ ├── ku_gl_floatbuffer.c
│ │ └── ku_gl_shader.c
│ ├── handler
│ │ ├── vh_anim.c
│ │ ├── vh_button.c
│ │ ├── vh_cv_body.c
│ │ ├── vh_cv_evnt.c
│ │ ├── vh_cv_scrl.c
│ │ ├── vh_drag.c
│ │ ├── vh_key.c
│ │ ├── vh_knob.c
│ │ ├── vh_roll.c
│ │ ├── vh_slider.c
│ │ ├── vh_table.c
│ │ ├── vh_tbl_body.c
│ │ ├── vh_tbl_evnt.c
│ │ ├── vh_tbl_head.c
│ │ ├── vh_tbl_scrl.c
│ │ ├── vh_textinput.c
│ │ └── vh_touch.c
│ ├── ku_bitmap.c
│ ├── ku_connector_wayland.c
│ ├── ku_css.c
│ ├── ku_draw.c
│ ├── ku_event.c
│ ├── ku_fontconfig.c
│ ├── ku_gen_css.c
│ ├── ku_gen_html.c
│ ├── ku_gen_textstyle.c
│ ├── ku_gen_type.c
│ ├── ku_html.c
│ ├── ku_png.c
│ ├── ku_recorder.c
│ ├── ku_rect.c
│ ├── ku_renderer_egl.c
│ ├── ku_renderer_soft.c
│ ├── ku_text.c
│ ├── ku_view.c
│ ├── ku_window.c
│ └── texture
│ │ ├── tg_css.c
│ │ ├── tg_knob.c
│ │ ├── tg_scaledimg.c
│ │ └── tg_text.c
├── mt_core
│ ├── mt_channel.c
│ ├── mt_log.c
│ ├── mt_map.c
│ ├── mt_memory.c
│ ├── mt_number.c
│ ├── mt_path.c
│ ├── mt_string.c
│ ├── mt_time.c
│ ├── mt_vector.c
│ ├── mt_wrapper.c
│ └── utf8.h
├── mt_core_ext
│ ├── ku_bitmap_ext.c
│ ├── mt_map_ext.c
│ └── mt_string_ext.c
├── mt_core_test
│ ├── mt_channel_test.c
│ ├── mt_core_test.c
│ ├── mt_map_test.c
│ ├── mt_memory_test.c
│ ├── mt_path_test.c
│ ├── mt_string_test.c
│ └── mt_vector_test.c
├── mt_math
│ ├── mt_math_2d.c
│ ├── mt_math_3d.c
│ ├── mt_matrix_3d.c
│ ├── mt_matrix_4d.c
│ ├── mt_vector_2d.c
│ ├── mt_vector_3d.c
│ └── mt_vector_4d.c
├── mt_math_test
│ └── mt_math_2d_test.c
└── sov
│ ├── draw.c
│ ├── gen.c
│ ├── jsmn.c
│ ├── json.c
│ ├── ku_bitmap_ext.c
│ ├── sov.c
│ └── tree.c
├── tst
├── a_tree.json
├── a_workspace.json
├── b_tree.json
├── b_workspace.json
├── empty_6_tree.json
├── empty_6_workspace.json
├── empty_tree.json
├── empty_workspace.json
├── feh_tree.json
├── feh_workspace.json
├── floating_tree.json
├── floating_workspace.json
├── master
│ ├── a_result_a.bmp
│ ├── a_result_b.bmp
│ ├── b_result_a.bmp
│ ├── b_result_b.bmp
│ ├── empty_6_result_a.bmp
│ ├── empty_6_result_b.bmp
│ ├── empty_result_a.bmp
│ ├── empty_result_b.bmp
│ ├── feh_result_a.bmp
│ ├── feh_result_b.bmp
│ ├── floating_result_a.bmp
│ ├── floating_result_b.bmp
│ ├── rotated_result_a.bmp
│ └── rotated_result_b.bmp
├── rotated_tree.json
├── rotated_workspace.json
├── runtests.sh
├── stylea
│ └── html
│ │ ├── main.css
│ │ └── main.html
└── styleb
│ └── html
│ ├── main.css
│ └── main.html
└── wlr-layer-shell-unstable-v1.xml
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | # BasedOnStyle: LLVM
4 | AccessModifierOffset: -2
5 | AlignAfterOpenBracket: AlwaysBreak
6 | AlignConsecutiveAssignments: true
7 | AlignConsecutiveDeclarations: true
8 | AlignEscapedNewlines: Right
9 | AlignOperands: true
10 | AlignTrailingComments: true
11 | AllowAllParametersOfDeclarationOnNextLine: true
12 | AllowShortBlocksOnASingleLine: true
13 | AllowShortCaseLabelsOnASingleLine: true
14 | AllowShortFunctionsOnASingleLine: false
15 | AllowShortIfStatementsOnASingleLine: true
16 | AllowShortLoopsOnASingleLine: true
17 | AlwaysBreakAfterDefinitionReturnType: None
18 | AlwaysBreakAfterReturnType: None
19 | AlwaysBreakBeforeMultilineStrings: true
20 | AlwaysBreakTemplateDeclarations: MultiLine
21 | BinPackArguments: false
22 | BinPackParameters: false
23 | BraceWrapping:
24 | AfterClass: false
25 | AfterControlStatement: false
26 | AfterEnum: false
27 | AfterFunction: true
28 | AfterNamespace: false
29 | AfterObjCDeclaration: false
30 | AfterStruct: false
31 | AfterUnion: false
32 | AfterExternBlock: false
33 | BeforeCatch: false
34 | BeforeElse: false
35 | IndentBraces: false
36 | SplitEmptyFunction: true
37 | SplitEmptyRecord: true
38 | SplitEmptyNamespace: true
39 | BreakBeforeBinaryOperators: None
40 | BreakBeforeBraces: Allman
41 | BreakBeforeInheritanceComma: false
42 | BreakInheritanceList: BeforeColon
43 | BreakBeforeTernaryOperators: true
44 | BreakConstructorInitializersBeforeComma: false
45 | BreakConstructorInitializers: BeforeColon
46 | BreakAfterJavaFieldAnnotations: false
47 | BreakStringLiterals: true
48 | ColumnLimit: 0
49 | CommentPragmas: '^ IWYU pragma:'
50 | CompactNamespaces: false
51 | ConstructorInitializerAllOnOneLineOrOnePerLine: false
52 | ConstructorInitializerIndentWidth: 4
53 | ContinuationIndentWidth: 4
54 | Cpp11BracedListStyle: true
55 | DerivePointerAlignment: false
56 | DisableFormat: false
57 | ExperimentalAutoDetectBinPacking: false
58 | FixNamespaceComments: true
59 | ForEachMacros:
60 | - foreach
61 | - Q_FOREACH
62 | - BOOST_FOREACH
63 | IncludeBlocks: Preserve
64 | IncludeCategories:
65 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
66 | Priority: 3
67 | - Regex: '^(<|"(gtest|gmock|isl|json)/)'
68 | Priority: 2
69 | - Regex: '.*'
70 | Priority: 1
71 | IncludeIsMainRegex: '(Test)?$'
72 | IndentCaseLabels: true
73 | IndentPPDirectives: BeforeHash
74 | IndentWidth: 4
75 | IndentWrappedFunctionNames: false
76 | JavaScriptQuotes: Leave
77 | JavaScriptWrapImports: true
78 | KeepEmptyLinesAtTheStartOfBlocks: true
79 | MacroBlockBegin: ''
80 | MacroBlockEnd: ''
81 | MaxEmptyLinesToKeep: 1
82 | NamespaceIndentation: None
83 | ObjCBinPackProtocolList: Auto
84 | ObjCBlockIndentWidth: 2
85 | ObjCSpaceAfterProperty: false
86 | ObjCSpaceBeforeProtocolList: true
87 | PenaltyBreakAssignment: 2
88 | PenaltyBreakBeforeFirstCallParameter: 19
89 | PenaltyBreakComment: 300
90 | PenaltyBreakFirstLessLess: 120
91 | PenaltyBreakString: 1000
92 | PenaltyBreakTemplateDeclaration: 10
93 | PenaltyExcessCharacter: 1000000
94 | PenaltyReturnTypeOnItsOwnLine: 60
95 | PointerAlignment: Left
96 | ReflowComments: true
97 | SortIncludes: true
98 | SortUsingDeclarations: true
99 | SpaceAfterCStyleCast: true
100 | SpaceAfterTemplateKeyword: true
101 | SpaceBeforeAssignmentOperators: true
102 | SpaceBeforeCpp11BracedList: false
103 | SpaceBeforeCtorInitializerColon: true
104 | SpaceBeforeInheritanceColon: true
105 | SpaceBeforeParens: ControlStatements
106 | SpaceBeforeRangeBasedForLoopColon: true
107 | SpaceInEmptyParentheses: false
108 | SpacesBeforeTrailingComments: 1
109 | SpacesInAngles: false
110 | SpacesInContainerLiterals: true
111 | SpacesInCStyleCastParentheses: false
112 | SpacesInParentheses: false
113 | SpacesInSquareBrackets: false
114 | Standard: Cpp11
115 | StatementMacros:
116 | - Q_UNUSED
117 | - QT_REQUIRE_VERSION
118 | TabWidth: 8
119 | UseTab: ForContinuationAndIndentation
120 | ...
121 |
122 |
--------------------------------------------------------------------------------
/.github/workflows/c.yml:
--------------------------------------------------------------------------------
1 | name: C CI
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | pull_request:
7 | branches: [ "main" ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v3
16 | - name: prepare deps
17 | run: sudo apt install -y meson ninja-build pkg-config libpng-dev libfreetype-dev libgl-dev libegl-dev libglew-dev libwayland-dev libxkbcommon-dev wayland-protocols libgles2-mesa-dev
18 | - name: configure
19 | run: meson setup build --buildtype=debug -Db_sanitize=address -Db_lundef=false
20 | - name: make
21 | run: ninja -C build
22 | - name: make check
23 | run: cd build && meson test
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | # Linker output
11 | *.ilk
12 | *.map
13 | *.exp
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Libraries
20 | *.lib
21 | *.a
22 | *.la
23 | *.lo
24 |
25 | # Shared objects (inc. Windows DLLs)
26 | *.dll
27 | *.so
28 | *.so.*
29 | *.dylib
30 |
31 | # Executables
32 | *.exe
33 | *.out
34 | *.app
35 | *.i*86
36 | *.x86_64
37 | *.hex
38 |
39 | # Debug files
40 | *.dSYM/
41 | *.su
42 | *.idb
43 | *.pdb
44 |
45 | # Kernel Module Compile Results
46 | *.mod*
47 | *.cmd
48 | .tmp_versions/
49 | modules.order
50 | Module.symvers
51 | Mkfile.old
52 | dkms.conf
53 |
54 | # Clang cache
55 | .cache/
56 |
--------------------------------------------------------------------------------
/contrib/systemd/sov.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=An overlay that shows schemas for all workspaces to make navigation in sway easier
3 | PartOf=graphical-session.target
4 | After=graphical-session.target
5 | ConditionEnvironment=WAYLAND_DISPLAY
6 |
7 | [Service]
8 | StandardInput=socket
9 | ExecStart=/usr/bin/sov
10 |
11 | [Install]
12 | WantedBy=graphical-session.target
--------------------------------------------------------------------------------
/contrib/systemd/sov.socket:
--------------------------------------------------------------------------------
1 | [Socket]
2 | ListenFIFO=%t/sov.sock
3 | SocketMode=0600
4 |
5 | [Install]
6 | WantedBy=sockets.target
--------------------------------------------------------------------------------
/meson.build:
--------------------------------------------------------------------------------
1 | project(
2 | 'sov',
3 | 'c',
4 | version: '0.94',
5 | license: 'MIT',
6 | default_options: ['c_std=gnu99',
7 | 'warning_level=3']
8 | )
9 |
10 | cc = meson.get_compiler('c')
11 |
12 | egl = dependency('egl')
13 | png = dependency('libpng')
14 | math = cc.find_library('m')
15 | wegl = dependency('wayland-egl')
16 | glesv2 = dependency('glesv2')
17 | freetype = dependency('freetype2')
18 | xkbcommon = dependency('xkbcommon')
19 |
20 | wayland_client = dependency('wayland-client',version : '>=1.21.0')
21 | wayland_cursor = dependency('wayland-cursor')
22 | wayland_protos = dependency('wayland-protocols')
23 | wayland_scanner_dep = dependency('wayland-scanner')
24 | wayland_scanner = find_program(
25 | wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner')
26 | )
27 |
28 | wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir')
29 |
30 | protocols = [
31 | [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
32 | [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
33 | [wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'],
34 | 'wlr-layer-shell-unstable-v1.xml'
35 | ]
36 |
37 | protos_src = []
38 | protos_headers = []
39 |
40 | foreach p : protocols
41 | xml = join_paths(p)
42 | protos_src += custom_target(
43 | xml.underscorify() + '_client_c',
44 | input: xml,
45 | output: '@BASENAME@-protocol.c',
46 | command: [wayland_scanner, 'public-code', '@INPUT@', '@OUTPUT@'],
47 | )
48 | protos_headers += custom_target(
49 | xml.underscorify() + '_client_h',
50 | input: xml,
51 | output: '@BASENAME@-client-protocol.h',
52 | command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'],
53 | )
54 | endforeach
55 |
56 |
57 | sov_dependencies = [wayland_client,
58 | wayland_cursor,
59 | png,
60 | freetype,
61 | math,
62 | glesv2,
63 | xkbcommon,
64 | egl,
65 | wegl]
66 |
67 | sov_version = '"@0@"'.format(meson.project_version())
68 | pkg_datadir = join_paths(get_option('prefix'), get_option('datadir')) / 'sov'
69 | add_project_arguments('-DPKG_DATADIR="' + pkg_datadir + '"',
70 | '-DSOV_VERSION=@0@'.format(sov_version),
71 | '-Wno-unused-parameter',
72 | language: 'c')
73 |
74 | if get_option('buildtype') == 'debug'
75 | add_project_arguments('-DDEBUG',language: 'c')
76 | endif
77 |
78 | sov_inc = include_directories(
79 | 'src/mt_math',
80 | 'src/mt_core',
81 | 'src/kinetic_ui',
82 | 'src/kinetic_ui/egl',
83 | 'src/kinetic_ui/handler',
84 | 'src/kinetic_ui/texture',
85 | 'src/sov',
86 | 'src/mt_core_ext')
87 |
88 | if build_machine.system() == 'freebsd'
89 | epoll = dependency('epoll-shim')
90 | pthread = dependency('threads')
91 | sov_dependencies += pthread
92 | sov_dependencies += epoll
93 | endif
94 |
95 | com_sources = ['src/sov/jsmn.c',
96 | 'src/sov/json.c',
97 | 'src/sov/tree.c',
98 | 'src/sov/gen.c',
99 | 'src/sov/ku_bitmap_ext.c',
100 |
101 | 'src/mt_core_ext/mt_string_ext.c',
102 | 'src/mt_core/mt_string.c',
103 | 'src/mt_core/mt_path.c',
104 | 'src/mt_core/mt_log.c',
105 | 'src/mt_core/mt_map.c',
106 | 'src/mt_core/mt_memory.c',
107 | 'src/mt_core/mt_number.c',
108 | 'src/mt_core/mt_time.c',
109 | 'src/mt_core/mt_vector.c',
110 | 'src/mt_core/mt_wrapper.c',
111 | 'src/mt_math/mt_matrix_4d.c',
112 |
113 | 'src/kinetic_ui/ku_event.c',
114 | 'src/kinetic_ui/ku_html.c',
115 | 'src/kinetic_ui/ku_css.c',
116 | 'src/kinetic_ui/egl/ku_gl.c',
117 | 'src/kinetic_ui/ku_rect.c',
118 | 'src/kinetic_ui/ku_bitmap.c',
119 | 'src/kinetic_ui/texture/tg_css.c',
120 | 'src/kinetic_ui/texture/tg_text.c',
121 | 'src/kinetic_ui/handler/vh_anim.c',
122 | 'src/kinetic_ui/handler/vh_button.c',
123 | 'src/kinetic_ui/handler/vh_drag.c',
124 | 'src/kinetic_ui/handler/vh_key.c',
125 | 'src/kinetic_ui/handler/vh_slider.c',
126 | 'src/kinetic_ui/ku_view.c',
127 | 'src/kinetic_ui/egl/ku_gl_atlas.c',
128 | 'src/kinetic_ui/egl/ku_gl_floatbuffer.c',
129 | 'src/kinetic_ui/egl/ku_gl_shader.c',
130 | 'src/kinetic_ui/ku_gen_html.c',
131 | 'src/kinetic_ui/ku_gen_css.c',
132 | 'src/kinetic_ui/ku_gen_type.c',
133 | 'src/kinetic_ui/ku_renderer_egl.c',
134 | 'src/kinetic_ui/ku_renderer_soft.c',
135 | 'src/kinetic_ui/ku_fontconfig.c',
136 | 'src/kinetic_ui/ku_connector_wayland.c',
137 | 'src/kinetic_ui/ku_window.c',
138 | 'src/kinetic_ui/ku_png.c',
139 | 'src/kinetic_ui/ku_draw.c',
140 | 'src/kinetic_ui/ku_text.c',
141 | 'src/kinetic_ui/ku_gen_textstyle.c'] + protos_src + protos_headers
142 |
143 | sov_sources = [com_sources, 'src/sov/sov.c']
144 | draw_sources = [com_sources, 'src/sov/draw.c']
145 |
146 | executable(
147 | 'sov',
148 | sov_sources,
149 | include_directories: [sov_inc],
150 | dependencies: sov_dependencies,
151 | install: true,
152 | )
153 |
154 | executable(
155 | 'draw',
156 | draw_sources,
157 | include_directories: [sov_inc],
158 | dependencies: sov_dependencies,
159 | install: false,
160 | )
161 |
162 | pkg_datadir = join_paths(get_option('prefix'), get_option('datadir')) / 'sov'
163 |
164 | install_data('res/html/main.html', install_dir : pkg_datadir / 'html' )
165 | install_data('res/html/main.css', install_dir : pkg_datadir / 'html' )
166 |
167 | install_data('contrib/systemd/sov.service', install_dir : get_option('libdir') / 'systemd' / 'user' )
168 | install_data('contrib/systemd/sov.socket', install_dir : get_option('libdir') / 'systemd' / 'user' )
169 |
170 | mt_core_test = executable(
171 | 'mt_core_test',
172 | ['src/mt_core/mt_log.c',
173 | 'src/mt_core/mt_memory.c',
174 | 'src/mt_core/mt_vector.c',
175 | 'src/mt_core/mt_map.c',
176 | 'src/mt_core/mt_string.c',
177 | 'src/mt_core/mt_channel.c',
178 | 'src/mt_core/mt_path.c',
179 | 'src/mt_core_test/mt_core_test.c',
180 | 'src/mt_core_test/mt_memory_test.c',
181 | 'src/mt_core_test/mt_vector_test.c',
182 | 'src/mt_core_test/mt_map_test.c',
183 | 'src/mt_core_test/mt_string_test.c',
184 | 'src/mt_core_test/mt_channel_test.c',
185 | 'src/mt_core_test/mt_path_test.c'
186 | ],
187 | include_directories: ['src/mt_core'],
188 | dependencies: sov_dependencies)
189 |
190 | test('MT_CORE_TEST', mt_core_test)
191 |
192 | scripttests = find_program('tst/runtests.sh')
193 |
194 | test('SCRIPTED TESTS', scripttests, timeout: 0, workdir : meson.current_source_dir(), args : [meson.current_build_dir(),meson.current_source_dir()])
195 |
--------------------------------------------------------------------------------
/res/html/main.css:
--------------------------------------------------------------------------------
1 | #main {
2 | border-radius: 10px;
3 | background-color: #00000044;
4 | }
5 |
6 | #base {
7 | margin: 10px;
8 | }
9 |
10 | .fullscale {
11 | height: 100%;
12 | width: 100%;
13 | }
14 |
15 | .colflex {
16 | display: flex;
17 | flex-direction: column;
18 | }
19 |
20 | .rowflex {
21 | display: flex;
22 | flex-direction: row;
23 | }
24 |
25 | .workspace {
26 | margin: 10px;
27 | border-radius: 8px;
28 | background-color: #000000FF;
29 | border-width: 1px;
30 | border-color: #555555FF;
31 | }
32 |
33 | .window {
34 | width: 100px;
35 | height: 80px;
36 | background-color: #222222FF;
37 | border-radius: 8px;
38 | border-width: 1px;
39 | border-color: #BCBCBCFF;
40 | }
41 |
42 | .window_active {
43 | width: 100px;
44 | height: 80px;
45 | background-color: #444444FF;
46 | border-radius: 8px;
47 | border-width: 1px;
48 | border-color: #BCBCBCFF;
49 | }
50 |
51 | .title {
52 | width: 100%;
53 | height: 21px;
54 | margin-top: 4px;
55 | margin-left: 4px;
56 | margin-right: 4px;
57 | margin-bottom: 2px;
58 | color: #FFFFFFFF;
59 | font-size: 16px;
60 | font-family: "Ubuntu Mono:style=Bold:size=14";
61 | }
62 |
63 | .content {
64 | width: 100%;
65 | height: 100%;
66 | margin-left: 4px;
67 | margin-right: 4px;
68 | color: #999999FF;
69 | vertical-align: top;
70 | font-size: 14px;
71 | font-family: "Ubuntu Mono:style=Bold:size=12";
72 | word-wrap: break-word;
73 | line-height: 12px;
74 | }
75 |
76 | .number {
77 | width: 20px;
78 | height: 20px;
79 | right: -14px;
80 | top: -9px;
81 | color: #FFFFFFFF;
82 | font-size: 18px;
83 | font-family: "Ubuntu Mono:style=Bold:size=16";
84 | }
85 |
--------------------------------------------------------------------------------
/res/html/main.html:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/screenshot.png
--------------------------------------------------------------------------------
/src/kinetic_ui/egl/ku_gl_atlas.c:
--------------------------------------------------------------------------------
1 | #ifndef _ku_gl_atlas_h
2 | #define _ku_gl_atlas_h
3 |
4 | #include "mt_map.c"
5 | #include "mt_matrix_4d.c"
6 | #include "mt_vector_4d.c"
7 |
8 | typedef struct _ku_gl_atlas_coords_t ku_gl_atlas_coords_t;
9 | struct _ku_gl_atlas_coords_t
10 | {
11 | float ltx;
12 | float lty;
13 | float rbx;
14 | float rby;
15 | int x;
16 | int y;
17 | int w;
18 | int h;
19 | };
20 |
21 | typedef struct _ku_gl_atlas_t ku_gl_atlas_t;
22 | struct _ku_gl_atlas_t
23 | {
24 | mt_map_t* coords;
25 | char* blocks;
26 | char is_full;
27 | int width;
28 | int height;
29 | int cols;
30 | int rows;
31 | };
32 |
33 | ku_gl_atlas_t* ku_gl_atlas_new(int w, int h);
34 | void ku_gl_atlas_del(void* p);
35 | char ku_gl_atlas_has(ku_gl_atlas_t* tm, char* id);
36 | ku_gl_atlas_coords_t ku_gl_atlas_get(ku_gl_atlas_t* tm, char* id);
37 | int ku_gl_atlas_put(ku_gl_atlas_t* tm, char* id, int w, int h);
38 |
39 | #endif
40 |
41 | #if __INCLUDE_LEVEL__ == 0
42 |
43 | #include "mt_memory.c"
44 | #include
45 |
46 | void ku_gl_atlas_desc(void* p, int level)
47 | {
48 | ku_gl_atlas_t* tm = p;
49 | printf("tm w %i h %i", tm->width, tm->height);
50 | }
51 |
52 | void ku_gl_atlas_desc_blocks(void* p, int level)
53 | {
54 | printf("tm blocks\n");
55 | }
56 |
57 | ku_gl_atlas_t* ku_gl_atlas_new(int w, int h)
58 | {
59 | int cols = w / 32;
60 | int rows = h / 32;
61 |
62 | ku_gl_atlas_t* tm = CAL(sizeof(ku_gl_atlas_t), ku_gl_atlas_del, ku_gl_atlas_desc);
63 | tm->coords = mt_map_new();
64 | tm->blocks = CAL(sizeof(char) * cols * rows, NULL, ku_gl_atlas_desc_blocks);
65 | tm->width = w;
66 | tm->height = h;
67 | tm->cols = cols;
68 | tm->rows = rows;
69 |
70 | return tm;
71 | }
72 |
73 | void ku_gl_atlas_del(void* p)
74 | {
75 | ku_gl_atlas_t* tm = (ku_gl_atlas_t*) p;
76 | REL(tm->coords);
77 | REL(tm->blocks);
78 | }
79 |
80 | char ku_gl_atlas_has(ku_gl_atlas_t* tm, char* id)
81 | {
82 | v4_t* coords = mt_map_get(tm->coords, id);
83 | if (coords) return 1;
84 | return 0;
85 | }
86 |
87 | ku_gl_atlas_coords_t ku_gl_atlas_get(ku_gl_atlas_t* tm, char* id)
88 | {
89 | ku_gl_atlas_coords_t* coords = mt_map_get(tm->coords, id);
90 | if (coords) return *coords;
91 | return (ku_gl_atlas_coords_t){0};
92 | }
93 |
94 | int ku_gl_atlas_put(ku_gl_atlas_t* tm, char* id, int w, int h)
95 | {
96 | if (w > tm->width || h > tm->height) return -1; // too big bitmap
97 |
98 | // get size of incoming rect
99 | int sx = ceil((float) w / 32.0);
100 | int sy = ceil((float) h / 32.0);
101 |
102 | int r = 0; // row
103 | int c = 0; // col
104 | int s = 0; // success
105 |
106 | for (r = 0; r < tm->rows; r++)
107 | {
108 | for (c = 0; c < tm->cols; c++)
109 | {
110 | int i = r * tm->cols + c;
111 |
112 | // if block is free, check if width and height of new rect fits
113 |
114 | if (tm->blocks[i] == 0)
115 | {
116 | s = 1; // assume success
117 | if (c + sx < tm->cols)
118 | {
119 | for (int tc = c; tc < c + sx; tc++)
120 | {
121 | int ti = r * tm->cols + tc; // test index
122 | if (tm->blocks[ti] == 1)
123 | {
124 | s = 0; // if block is occupied test is failed
125 | break;
126 | }
127 | }
128 | }
129 | else
130 | s = 0; // doesn't fit
131 |
132 | if (r + sy < tm->rows && s == 1)
133 | {
134 | for (int tr = r; tr < r + sy; tr++)
135 | {
136 | int ti = tr * tm->cols + c; // test index
137 | if (tm->blocks[ti] == 1)
138 | {
139 | s = 0; // if block is occupied test is failed
140 | break;
141 | }
142 | }
143 | }
144 | else
145 | s = 0; // doesn't fit
146 | }
147 | if (s == 1) break;
148 | }
149 | if (s == 1) break;
150 | }
151 |
152 | if (s == 1)
153 | {
154 | // flip blocks to occupied
155 | for (int nr = r; nr < r + sy; nr++)
156 | {
157 | for (int nc = c; nc < c + sx; nc++)
158 | {
159 | int ni = nr * tm->cols + nc;
160 | tm->blocks[ni] = 1;
161 | }
162 | }
163 |
164 | int ncx = c * 32;
165 | int ncy = r * 32;
166 | int rbx = ncx + w;
167 | int rby = ncy + h;
168 |
169 | ku_gl_atlas_coords_t* coords = HEAP(
170 | ((ku_gl_atlas_coords_t){
171 | .ltx = (float) ncx / (float) tm->width,
172 | .lty = (float) ncy / (float) tm->height,
173 | .rbx = (float) rbx / (float) tm->width,
174 | .rby = (float) rby / (float) tm->height,
175 | .x = ncx,
176 | .y = ncy,
177 | .w = w,
178 | .h = h}));
179 |
180 | MPUTR(tm->coords, id, coords);
181 | }
182 | else
183 | return -2; // texmap is full
184 |
185 | return 0; // success
186 | }
187 |
188 | #endif
189 |
--------------------------------------------------------------------------------
/src/kinetic_ui/egl/ku_gl_floatbuffer.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_floatbuffer_h
2 | #define ku_floatbuffer_h
3 |
4 | #include "mt_memory.c"
5 | #include
6 | #include
7 |
8 | typedef struct ku_floatbuffer_t ku_floatbuffer_t;
9 | struct ku_floatbuffer_t
10 | {
11 | GLfloat* data;
12 | size_t pos;
13 | size_t cap;
14 | char changed;
15 | };
16 |
17 | ku_floatbuffer_t* ku_floatbuffer_new(void);
18 | void ku_floatbuffer_del(void* fb);
19 | void ku_floatbuffer_reset(ku_floatbuffer_t* fb);
20 | void ku_floatbuffer_add(ku_floatbuffer_t* fb, GLfloat* data, size_t count);
21 |
22 | #endif
23 |
24 | #if __INCLUDE_LEVEL__ == 0
25 |
26 | void ku_floatbuffer_desc(void* p, int level)
27 | {
28 | printf("fb");
29 | }
30 |
31 | void ku_floatbuffer_desc_data(void* p, int level)
32 | {
33 | printf("fb data");
34 | }
35 |
36 | ku_floatbuffer_t* ku_floatbuffer_new()
37 | {
38 | ku_floatbuffer_t* fb = CAL(sizeof(ku_floatbuffer_t), ku_floatbuffer_del, ku_floatbuffer_desc);
39 | fb->data = CAL(sizeof(GLfloat) * 10, NULL, ku_floatbuffer_desc_data);
40 | fb->pos = 0;
41 | fb->cap = 10;
42 |
43 | return fb;
44 | }
45 |
46 | void ku_floatbuffer_del(void* pointer)
47 | {
48 | ku_floatbuffer_t* fb = pointer;
49 | REL(fb->data);
50 | }
51 |
52 | void ku_floatbuffer_reset(ku_floatbuffer_t* fb)
53 | {
54 | fb->pos = 0;
55 | }
56 |
57 | void ku_floatbuffer_expand(ku_floatbuffer_t* fb)
58 | {
59 | assert(fb->cap < SIZE_MAX / 2);
60 | fb->cap *= 2;
61 | fb->data = mt_memory_realloc(fb->data, sizeof(void*) * fb->cap);
62 | }
63 |
64 | void ku_floatbuffer_add(ku_floatbuffer_t* fb, GLfloat* data, size_t count)
65 | {
66 | while (fb->pos + count >= fb->cap) ku_floatbuffer_expand(fb);
67 | memcpy(fb->data + fb->pos, data, sizeof(GLfloat) * count);
68 | fb->pos += count;
69 | fb->changed = 1;
70 | }
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/src/kinetic_ui/egl/ku_gl_shader.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_gl_shader_h
2 | #define ku_gl_shader_h
3 |
4 | #include
5 |
6 | typedef struct _glsha_t
7 | {
8 | GLuint name;
9 | GLint uni_loc[13];
10 | } glsha_t;
11 |
12 | glsha_t ku_gl_shader_create(
13 | const char* vertex_source,
14 | const char* fragment_source,
15 | int attribute_locations_length,
16 | const char** attribute_structure,
17 | int uniform_locations_length,
18 | const char** uniform_structure);
19 |
20 | #endif
21 |
22 | #if __INCLUDE_LEVEL__ == 0
23 |
24 | #include
25 |
26 | GLuint ku_gl_shader_compile(GLenum type, const GLchar* source)
27 | {
28 | GLint status, logLength, realLength;
29 | GLuint shader = 0;
30 |
31 | status = 0;
32 | shader = glCreateShader(type);
33 |
34 | if (shader > 0)
35 | {
36 | glShaderSource(shader, 1, &source, NULL);
37 | glCompileShader(shader);
38 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
39 |
40 | if (logLength > 0)
41 | {
42 | GLchar log[logLength];
43 |
44 | glGetShaderInfoLog(shader, logLength, &realLength, log);
45 |
46 | printf("Shader compile log: %s\n", log);
47 | }
48 |
49 | glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
50 |
51 | if (status != GL_TRUE)
52 | return 0;
53 | }
54 | else
55 | printf("Cannot create shader\n");
56 |
57 | return shader;
58 | }
59 |
60 | int ku_gl_shader_link(GLuint program)
61 | {
62 | GLint status, logLength, realLength;
63 |
64 | glLinkProgram(program);
65 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
66 |
67 | if (logLength > 0)
68 | {
69 | GLchar log[logLength];
70 | glGetProgramInfoLog(program, logLength, &realLength, log);
71 | printf("Program link log : %i %s\n", realLength, log);
72 | }
73 |
74 | glGetProgramiv(program, GL_LINK_STATUS, &status);
75 | if (status == GL_TRUE)
76 | return 1;
77 | return 0;
78 | }
79 |
80 | glsha_t ku_gl_shader_create(
81 | const char* vertex_source,
82 | const char* fragment_source,
83 | int attribute_locations_length,
84 | const char** attribute_structure,
85 | int uniform_locations_length,
86 | const char** uniform_structure)
87 | {
88 | glsha_t sh = {0};
89 |
90 | sh.name = glCreateProgram();
91 |
92 | GLuint vertex_shader = ku_gl_shader_compile(GL_VERTEX_SHADER, vertex_source);
93 | if (vertex_shader == 0) printf("Failed to compile vertex shader : %s\n", vertex_source);
94 |
95 | GLuint fragment_shader = ku_gl_shader_compile(GL_FRAGMENT_SHADER, fragment_source);
96 | if (fragment_shader == 0) printf("Failed to compile fragment shader : %s\n", fragment_source);
97 |
98 | glAttachShader(sh.name, vertex_shader);
99 | glAttachShader(sh.name, fragment_shader);
100 |
101 | for (int index = 0; index < attribute_locations_length; index++)
102 | {
103 | const GLchar* name = attribute_structure[index];
104 | glBindAttribLocation(sh.name, index, name);
105 | }
106 |
107 | int success = ku_gl_shader_link(sh.name);
108 |
109 | if (success == 1)
110 | {
111 | for (int index = 0; index < uniform_locations_length; index++)
112 | {
113 | const GLchar* name = uniform_structure[index];
114 | GLint location = glGetUniformLocation(sh.name, name);
115 | sh.uni_loc[index] = location;
116 | }
117 | }
118 | else
119 | printf("Failed to link shader program\n");
120 |
121 | if (vertex_shader > 0)
122 | {
123 | glDetachShader(sh.name, vertex_shader);
124 | glDeleteShader(vertex_shader);
125 | }
126 |
127 | if (fragment_shader > 0)
128 | {
129 | glDetachShader(sh.name, fragment_shader);
130 | glDeleteShader(fragment_shader);
131 | }
132 |
133 | return sh;
134 | }
135 |
136 | #endif
137 |
--------------------------------------------------------------------------------
/src/kinetic_ui/handler/vh_button.c:
--------------------------------------------------------------------------------
1 | #ifndef vh_button_h
2 | #define vh_button_h
3 |
4 | #include "ku_view.c"
5 |
6 | typedef enum _vh_button_type_t
7 | {
8 | VH_BUTTON_NORMAL,
9 | VH_BUTTON_TOGGLE
10 | } vh_button_type_t;
11 |
12 | typedef enum _vh_button_state_t
13 | {
14 | VH_BUTTON_UP,
15 | VH_BUTTON_DOWN
16 | } vh_button_state_t;
17 |
18 | typedef struct _vh_button_t vh_button_t;
19 |
20 | enum vh_button_event_id
21 | {
22 | VH_BUTTON_EVENT
23 | };
24 |
25 | typedef struct _vh_button_event_t
26 | {
27 | enum vh_button_event_id id;
28 | vh_button_t* vh;
29 | ku_view_t* view;
30 | ku_event_t ev;
31 | } vh_button_event_t;
32 |
33 | struct _vh_button_t
34 | {
35 | void (*on_event)(vh_button_event_t);
36 | vh_button_type_t type;
37 | vh_button_state_t state;
38 |
39 | ku_view_t* offview;
40 | ku_view_t* onview;
41 | char enabled;
42 | };
43 |
44 | void vh_button_add(ku_view_t* view, vh_button_type_t type, void (*on_event)(vh_button_event_t));
45 | void vh_button_set_state(ku_view_t* view, vh_button_state_t state);
46 | void vh_button_set_enabled(ku_view_t* view, int flag);
47 |
48 | #endif
49 |
50 | #if __INCLUDE_LEVEL__ == 0
51 |
52 | #include "vh_anim.c"
53 |
54 | void vh_button_on_anim(vh_anim_event_t event)
55 | {
56 | ku_view_t* btnview = (ku_view_t*) event.userdata;
57 | vh_button_t* vh = btnview->evt_han_data;
58 |
59 | // if offview alpha is 0 and state is released
60 |
61 | if (vh->type == VH_BUTTON_NORMAL)
62 | {
63 | if (vh->offview->texture.alpha < 0.0001 && event.view == vh->offview)
64 | {
65 | vh_anim_alpha(vh->offview, 0.0, 1.0, 10, AT_LINEAR);
66 | }
67 | }
68 | }
69 |
70 | int vh_button_evt(ku_view_t* view, ku_event_t ev)
71 | {
72 | vh_button_t* vh = view->evt_han_data;
73 |
74 | if (vh->enabled)
75 | {
76 | if (ev.type == KU_EVENT_MOUSE_DOWN)
77 | {
78 | if (vh->type == VH_BUTTON_NORMAL)
79 | {
80 | vh->state = VH_BUTTON_DOWN;
81 |
82 | if (vh->offview)
83 | vh_anim_alpha(vh->offview, 1.0, 0.0, 10, AT_LINEAR);
84 | if (vh->onview)
85 | vh_anim_alpha(vh->onview, 0.0, 1.0, 10, AT_LINEAR);
86 | }
87 | }
88 | else if (ev.type == KU_EVENT_MOUSE_UP)
89 | {
90 | if (vh->type == VH_BUTTON_TOGGLE)
91 | {
92 | if (vh->state == VH_BUTTON_UP)
93 | {
94 | vh->state = VH_BUTTON_DOWN;
95 | if (vh->offview)
96 | vh_anim_alpha(vh->offview, 1.0, 0.0, 10, AT_LINEAR);
97 | if (vh->onview)
98 | vh_anim_alpha(vh->onview, 0.0, 1.0, 10, AT_LINEAR);
99 | }
100 | else
101 | {
102 | vh->state = VH_BUTTON_UP;
103 | if (vh->offview)
104 | vh_anim_alpha(vh->offview, 0.0, 1.0, 10, AT_LINEAR);
105 | if (vh->onview)
106 | vh_anim_alpha(vh->onview, 1.0, 0.0, 10, AT_LINEAR);
107 | }
108 |
109 | vh_button_event_t event = {.id = VH_BUTTON_EVENT, .view = view, .vh = vh, .ev = ev};
110 | if (vh->on_event)
111 | (*vh->on_event)(event);
112 | }
113 | else
114 | {
115 | vh->state = VH_BUTTON_UP;
116 |
117 | vh_button_event_t event = {.id = VH_BUTTON_EVENT, .view = view, .vh = vh, .ev = ev};
118 | if (vh->on_event)
119 | (*vh->on_event)(event);
120 |
121 | /* if (vh->offview) vh_anim_alpha(vh->offview, 1.0, 0.0, 10, AT_LINEAR); */
122 | /* if (vh->onview) vh_anim_alpha(vh->onview, 0.0, 1.0, 10, AT_LINEAR); */
123 | }
124 | }
125 | }
126 |
127 | return 0;
128 | }
129 |
130 | void vh_button_set_state(ku_view_t* view, vh_button_state_t state)
131 | {
132 | vh_button_t* vh = view->evt_han_data;
133 |
134 | if (vh->enabled)
135 | {
136 | vh->state = state;
137 |
138 | if (state)
139 | {
140 | if (vh->offview)
141 | vh_anim_alpha(vh->offview, 1.0, 0.0, 10, AT_LINEAR);
142 | if (vh->onview)
143 | vh_anim_alpha(vh->onview, 0.0, 1.0, 10, AT_LINEAR);
144 | }
145 | else
146 | {
147 | if (vh->offview)
148 | vh_anim_alpha(vh->offview, 0.0, 1.0, 10, AT_LINEAR);
149 | if (vh->onview)
150 | vh_anim_alpha(vh->onview, 1.0, 0.0, 10, AT_LINEAR);
151 | }
152 | }
153 | }
154 |
155 | void vh_button_del(void* p)
156 | {
157 | /* vh_button_t* vh = p; */
158 | }
159 |
160 | void vh_button_desc(void* p, int level)
161 | {
162 | printf("vh_button");
163 | }
164 |
165 | void vh_button_add(ku_view_t* view, vh_button_type_t type, void (*on_event)(vh_button_event_t))
166 | {
167 | assert(view->evt_han == NULL && view->evt_han_data == NULL);
168 |
169 | vh_button_t* vh = CAL(sizeof(vh_button_t), vh_button_del, vh_button_desc);
170 | vh->on_event = on_event;
171 | vh->type = type;
172 | vh->state = VH_BUTTON_UP;
173 | vh->enabled = 1;
174 |
175 | if (view->views->length > 0)
176 | {
177 | vh->offview = view->views->data[0];
178 | vh_anim_add(vh->offview, vh_button_on_anim, view);
179 | }
180 | if (view->views->length > 1)
181 | {
182 | vh->type = VH_BUTTON_TOGGLE;
183 | vh->onview = view->views->data[1];
184 | vh_anim_add(vh->onview, vh_button_on_anim, view);
185 | }
186 |
187 | if (vh->offview)
188 | ku_view_set_texture_alpha(vh->offview, 1.0, 0);
189 | if (vh->onview)
190 | ku_view_set_texture_alpha(vh->onview, 0.0, 0);
191 |
192 | view->evt_han = vh_button_evt;
193 | view->evt_han_data = vh;
194 | }
195 |
196 | void vh_button_set_enabled(ku_view_t* view, int flag)
197 | {
198 | vh_button_t* vh = view->evt_han_data;
199 |
200 | if (flag)
201 | {
202 | if (vh->enabled == 0 && vh->offview)
203 | vh_anim_alpha(vh->offview, 0.3, 1.0, 10, AT_LINEAR);
204 | }
205 | else
206 | {
207 | if (vh->enabled == 1 && vh->offview)
208 | vh_anim_alpha(vh->offview, 1.0, 0.3, 10, AT_LINEAR);
209 | }
210 |
211 | vh->enabled = flag;
212 | }
213 |
214 | #endif
215 |
--------------------------------------------------------------------------------
/src/kinetic_ui/handler/vh_cv_body.c:
--------------------------------------------------------------------------------
1 | /* content view body */
2 |
3 | #ifndef vh_cv_body_h
4 | #define vh_cv_body_h
5 |
6 | #include "ku_view.c"
7 |
8 | typedef struct _vh_cv_body_t
9 | {
10 | void* userdata;
11 |
12 | ku_view_t* content;
13 | float cw; // content width
14 | float ch; // content height
15 | float px;
16 | float py;
17 | float zoom;
18 | } vh_cv_body_t;
19 |
20 | void vh_cv_body_attach(
21 | ku_view_t* view,
22 | void* userdata);
23 |
24 | void vh_cv_body_set_content_size(
25 | ku_view_t* view,
26 | int cw,
27 | int ch);
28 |
29 | void vh_cv_body_move(
30 | ku_view_t* view,
31 | float dx,
32 | float dy);
33 |
34 | void vh_cv_body_zoom(
35 | ku_view_t* view,
36 | float s,
37 | int x,
38 | int y);
39 |
40 | void vh_cv_body_reset(
41 | ku_view_t* view);
42 |
43 | void vh_cv_body_hjump(
44 | ku_view_t* view,
45 | float dx);
46 |
47 | void vh_cv_body_vjump(
48 | ku_view_t* view,
49 | int topindex);
50 |
51 | #endif
52 |
53 | #if __INCLUDE_LEVEL__ == 0
54 |
55 | #include "tg_scaledimg.c"
56 |
57 | void vh_cv_body_del(void* p)
58 | {
59 | }
60 |
61 | void vh_cv_body_desc(void* p, int level)
62 | {
63 | printf("vh_cv_body");
64 | }
65 |
66 | void vh_cv_body_attach(
67 | ku_view_t* view,
68 | void* userdata)
69 | {
70 | assert(view->evt_han == NULL && view->evt_han_data == NULL);
71 |
72 | vh_cv_body_t* vh = CAL(sizeof(vh_cv_body_t), vh_cv_body_del, vh_cv_body_desc);
73 | vh->userdata = userdata;
74 | vh->content = view->views->data[0];
75 | vh->zoom = 1.0;
76 |
77 | vh->cw = 1;
78 | vh->ch = 1;
79 |
80 | view->evt_han_data = vh;
81 | }
82 |
83 | void vh_cv_body_set_content_size(
84 | ku_view_t* view,
85 | int cw,
86 | int ch)
87 | {
88 | vh_cv_body_t* vh = view->evt_han_data;
89 |
90 | vh->cw = cw;
91 | vh->ch = ch;
92 |
93 | ku_rect_t lf = view->frame.local; // local frame
94 |
95 | float cr = (float) ch / (float) cw; // content aspect ratio
96 |
97 | /* fit width first */
98 |
99 | float nw = lf.w;
100 | float nh = nw * cr;
101 |
102 | vh->zoom = (float) nw / cw;
103 |
104 | if (nh > lf.h)
105 | {
106 | cr = lf.h / nh;
107 |
108 | nh = lf.h;
109 | nw *= cr;
110 | vh->zoom = (float) nh / ch;
111 | }
112 |
113 | ku_rect_t frame = vh->content->frame.local;
114 | frame.x = (lf.w - nw) / 2.0;
115 | frame.y = (lf.h - nh) / 2.0;
116 | frame.w = nw;
117 | frame.h = nh;
118 |
119 | ku_view_set_frame(vh->content, frame);
120 |
121 | tg_scaledimg_set_content_size(vh->content, cw, ch);
122 | tg_scaledimg_gen(vh->content);
123 | }
124 |
125 | void vh_cv_body_move(
126 | ku_view_t* view,
127 | float dx,
128 | float dy)
129 | {
130 | vh_cv_body_t* vh = view->evt_han_data;
131 |
132 | ku_rect_t frame = vh->content->frame.local;
133 | frame.x += dx;
134 | frame.y += dy;
135 | ku_view_set_frame(vh->content, frame);
136 | }
137 |
138 | void vh_cv_body_zoom(
139 | ku_view_t* view,
140 | float z,
141 | int x,
142 | int y)
143 | {
144 | vh_cv_body_t* vh = view->evt_han_data;
145 |
146 | ku_rect_t gf = vh->content->frame.global;
147 | ku_rect_t lf = vh->content->frame.local;
148 |
149 | /* partial width and height from mouse position */
150 |
151 | float pw = (float) x - gf.x;
152 | float ph = (float) y - gf.y;
153 |
154 | /* ratios */
155 |
156 | float rw = pw / gf.w;
157 | float rh = ph / gf.h;
158 |
159 | vh->zoom = z;
160 | if (vh->zoom < 0.001)
161 | vh->zoom = 0.001;
162 |
163 | float nw = vh->cw * vh->zoom;
164 | float nh = vh->ch * vh->zoom;
165 |
166 | lf.x = (float) x - rw * nw - view->frame.global.x;
167 | lf.y = (float) y - rh * nh - view->frame.global.y;
168 | lf.w = nw;
169 | lf.h = nh;
170 |
171 | ku_view_set_frame(vh->content, lf);
172 | tg_scaledimg_gen(vh->content);
173 | }
174 |
175 | void vh_cv_body_reset(
176 | ku_view_t* view)
177 | {
178 | }
179 |
180 | void vh_cv_body_hjump(
181 | ku_view_t* view,
182 | float x)
183 | {
184 | }
185 |
186 | void vh_cv_body_vjump(
187 | ku_view_t* view,
188 | int topindex)
189 | {
190 | }
191 |
192 | #endif
193 |
--------------------------------------------------------------------------------
/src/kinetic_ui/handler/vh_cv_scrl.c:
--------------------------------------------------------------------------------
1 | #ifndef vh_cv_scrl_h
2 | #define vh_cv_scrl_h
3 |
4 | #include "ku_view.c"
5 | #include "vh_cv_body.c"
6 |
7 | typedef struct _vh_cv_scrl_t
8 | {
9 | ku_view_t* tbody_view;
10 | ku_view_t* vert_v;
11 | ku_view_t* hori_v;
12 | int state; // 0 scroll 1 open 2 close
13 | int steps;
14 | size_t item_cnt;
15 | void* userdata;
16 | } vh_cv_scrl_t;
17 |
18 | void vh_cv_scrl_attach(
19 | ku_view_t* view,
20 | ku_view_t* tbody_view,
21 | void* userdata);
22 |
23 | void vh_cv_scrl_update(ku_view_t* view);
24 | void vh_cv_scrl_show(ku_view_t* view);
25 | void vh_cv_scrl_hide(ku_view_t* view);
26 | void vh_cv_scrl_set_item_count(ku_view_t* view, size_t count);
27 | void vh_cv_scrl_scroll_v(ku_view_t* view, int y);
28 | void vh_cv_scrl_scroll_h(ku_view_t* view, int x);
29 |
30 | #endif
31 |
32 | #if __INCLUDE_LEVEL__ == 0
33 |
34 | void vh_cv_scrl_del(void* p)
35 | {
36 | vh_cv_scrl_t* vh = p;
37 | REL(vh->vert_v);
38 | REL(vh->hori_v);
39 | }
40 |
41 | void vh_cv_scrl_desc(void* p, int level)
42 | {
43 | printf("vh_cv_scrl");
44 | }
45 |
46 | void vh_cv_scrl_attach(
47 | ku_view_t* view,
48 | ku_view_t* tbody_view,
49 | void* userdata)
50 | {
51 | vh_cv_scrl_t* vh = CAL(sizeof(vh_cv_scrl_t), vh_cv_scrl_del, vh_cv_scrl_desc);
52 | vh->userdata = userdata;
53 | vh->tbody_view = tbody_view;
54 |
55 | assert(view->views->length > 1);
56 |
57 | vh->vert_v = RET(view->views->data[0]);
58 | vh->hori_v = RET(view->views->data[1]);
59 |
60 | ku_view_set_texture_alpha(vh->hori_v, 0.0, 0);
61 | ku_view_set_texture_alpha(vh->vert_v, 0.0, 0);
62 |
63 | view->evt_han_data = vh;
64 | }
65 |
66 | void vh_cv_scrl_set_item_count(ku_view_t* view, size_t count)
67 | {
68 | vh_cv_scrl_t* vh = view->evt_han_data;
69 |
70 | vh->item_cnt = count;
71 | }
72 |
73 | void vh_cv_scrl_update(ku_view_t* view)
74 | {
75 | vh_cv_scrl_t* vh = view->evt_han_data;
76 | vh_cv_body_t* bvh = vh->tbody_view->evt_han_data;
77 |
78 | ku_rect_t vf = view->frame.local;
79 | ku_rect_t cf = bvh->content->frame.local;
80 |
81 | float pratio = -cf.y / cf.h;
82 | float sratio = cf.h / vf.h;
83 |
84 | if (sratio > 1.0)
85 | {
86 | float hth = (vf.h - vh->hori_v->frame.local.h) * (1 / sratio);
87 | float pos = (vf.h - vh->hori_v->frame.local.h) * pratio;
88 |
89 | if (vh->state == 2)
90 | {
91 | pos += hth / 2.0;
92 | hth = 1.0;
93 | }
94 |
95 | ku_rect_t frame = vh->vert_v->frame.local;
96 | frame.h += (hth - frame.h) / 2.0;
97 | frame.y += (pos - frame.y) / 2.0;
98 |
99 | ku_view_set_frame(vh->vert_v, frame);
100 | }
101 |
102 | pratio = -cf.x / cf.w;
103 | sratio = cf.w / vf.w;
104 |
105 | if (sratio > 1.0)
106 | {
107 | float wth = (vf.w - vh->vert_v->frame.local.w) * (1 / sratio);
108 | float pos = (vf.w - vh->vert_v->frame.local.w) * pratio;
109 |
110 | if (vh->state == 2)
111 | {
112 | pos += wth / 2.0;
113 | wth = 1.0;
114 | }
115 |
116 | ku_rect_t frame = vh->hori_v->frame.local;
117 | frame.w += (wth - frame.w) / 2.0;
118 | frame.x += (pos - frame.x) / 2.0;
119 |
120 | ku_view_set_frame(vh->hori_v, frame);
121 | }
122 |
123 | if (vh->state > 0)
124 | {
125 | vh->steps += 1;
126 | if (vh->steps == 5)
127 | {
128 | if (vh->state == 2)
129 | {
130 | ku_view_set_texture_alpha(vh->hori_v, 0.0, 0);
131 | ku_view_set_texture_alpha(vh->vert_v, 0.0, 0);
132 | }
133 | vh->state = 0;
134 | }
135 | }
136 | }
137 |
138 | void vh_cv_scrl_show(ku_view_t* view)
139 | {
140 | vh_cv_scrl_t* vh = view->evt_han_data;
141 |
142 | vh->state = 1;
143 | vh->steps = 0;
144 | ku_view_set_texture_alpha(vh->hori_v, 1.0, 0);
145 | ku_view_set_texture_alpha(vh->vert_v, 1.0, 0);
146 | }
147 |
148 | void vh_cv_scrl_hide(ku_view_t* view)
149 | {
150 | vh_cv_scrl_t* vh = view->evt_han_data;
151 | vh->state = 2;
152 | vh->steps = 0;
153 | }
154 |
155 | void vh_cv_scrl_scroll_v(ku_view_t* view, int y)
156 | {
157 | /* vh_cv_scrl_t* vh = view->evt_han_data; */
158 | /* vh_cv_body_t* bvh = vh->tbody_view->evt_han_data; */
159 |
160 | /* if (bvh->items->length > 0 && vh->item_cnt > 0) */
161 | /* { */
162 | /* // int vert_pos = bvh->top_index; */
163 | /* int vert_vis = bvh->bot_index - bvh->top_index; */
164 | /* int vert_max = vh->item_cnt; */
165 |
166 | /* if (vert_max > 1) */
167 | /* { */
168 | /* float sratio = (float) vert_vis / (float) vert_max; */
169 | /* float height = (view->frame.local.h - view->frame.local.h * sratio); */
170 | /* float pratio = (float) y / height; */
171 |
172 | /* if (pratio < 0.0) pratio = 0.0; */
173 | /* if (pratio > 1.0) pratio = 1.0; */
174 | /* int topindex = pratio * (vert_max - vert_vis); */
175 |
176 | /* vh_cv_body_vjump(vh->tbody_view, topindex); */
177 |
178 | /* ku_rect_t frame = vh->vert_v->frame.local; */
179 | /* frame.h = view->frame.local.h * sratio; */
180 | /* frame.y = y; */
181 |
182 | /* ku_view_set_frame(vh->vert_v, frame); */
183 | /* } */
184 | /* } */
185 | }
186 |
187 | void vh_cv_scrl_scroll_h(ku_view_t* view, int x)
188 | {
189 | /* vh_cv_scrl_t* vh = view->evt_han_data; */
190 | /* vh_cv_body_t* bvh = vh->tbody_view->evt_han_data; */
191 |
192 | /* if (bvh->items->length > 0 && vh->item_cnt > 0) */
193 | /* { */
194 | /* ku_view_t* head = bvh->items->data[0]; */
195 |
196 | /* // float hori_pos = -head->frame.local.x; */
197 | /* float hori_vis = view->frame.local.w; */
198 | /* float hori_max = head->frame.local.w; */
199 |
200 | /* if (hori_max > 1.0) */
201 | /* { */
202 | /* float sratio = (float) hori_vis / (float) hori_max; */
203 | /* float width = (view->frame.local.w - view->frame.local.w * sratio); */
204 | /* float pratio = (float) x / width; */
205 |
206 | /* if (pratio < 0.0) pratio = 0.0; */
207 | /* if (pratio > 1.0) pratio = 1.0; */
208 | /* float dx = pratio * (hori_max - hori_vis); */
209 |
210 | /* vh_cv_body_hjump(vh->tbody_view, -dx); */
211 | /* vh_cv_head_jump(vh->thead_view, -dx); */
212 |
213 | /* ku_rect_t frame = vh->hori_v->frame.local; */
214 | /* frame.w = view->frame.local.w * sratio; */
215 | /* frame.x = x; */
216 |
217 | /* ku_view_set_frame(vh->hori_v, frame); */
218 | /* } */
219 | /* } */
220 | }
221 |
222 | #endif
223 |
--------------------------------------------------------------------------------
/src/kinetic_ui/handler/vh_drag.c:
--------------------------------------------------------------------------------
1 | #ifndef vh_drag_h
2 | #define vh_drag_h
3 |
4 | #include "ku_event.c"
5 | #include "ku_view.c"
6 |
7 | enum vh_drag_event_id
8 | {
9 | VH_DRAG_MOVE,
10 | VH_DRAG_DROP
11 | };
12 |
13 | typedef struct _vh_drag_t vh_drag_t;
14 |
15 | typedef struct _vh_drag_event_t
16 | {
17 | enum vh_drag_event_id id;
18 | vh_drag_t* vh;
19 | ku_view_t* view;
20 | ku_view_t* dragged_view;
21 | } vh_drag_event_t;
22 |
23 | struct _vh_drag_t
24 | {
25 | void (*on_event)(vh_drag_event_t);
26 | ku_view_t* dragged_view;
27 | };
28 |
29 | void vh_drag_attach(ku_view_t* view, void (*on_event)(vh_drag_event_t));
30 | void vh_drag_drag(ku_view_t* view, ku_view_t* item);
31 |
32 | #endif
33 |
34 | #if __INCLUDE_LEVEL__ == 0
35 |
36 | int vh_drag_evt(ku_view_t* view, ku_event_t ev)
37 | {
38 | if (ev.type == KU_EVENT_MOUSE_MOVE && ev.drag)
39 | {
40 | vh_drag_t* vh = view->evt_han_data;
41 |
42 | if (vh->dragged_view)
43 | {
44 | ku_rect_t frame = vh->dragged_view->frame.local;
45 | frame.x = ev.x - frame.w / 2;
46 | frame.y = ev.y - frame.h / 2;
47 | ku_view_set_frame(vh->dragged_view, frame);
48 |
49 | vh_drag_event_t event = {.id = VH_DRAG_MOVE, .vh = vh, .view = view, .dragged_view = vh->dragged_view};
50 | if (vh->on_event)
51 | (*vh->on_event)(event);
52 | }
53 | }
54 | if (ev.type == KU_EVENT_MOUSE_UP && ev.drag)
55 | {
56 | vh_drag_t* vh = view->evt_han_data;
57 |
58 | if (vh->dragged_view)
59 | {
60 | vh_drag_event_t event = {.id = VH_DRAG_DROP, .vh = vh, .view = view, .dragged_view = vh->dragged_view};
61 | if (vh->on_event)
62 | (*vh->on_event)(event);
63 |
64 | REL(vh->dragged_view);
65 | vh->dragged_view = NULL;
66 | }
67 | }
68 |
69 | return 1;
70 | }
71 |
72 | void vh_drag_del(void* p)
73 | {
74 | vh_drag_t* vh = p;
75 |
76 | if (vh->dragged_view) REL(vh->dragged_view);
77 | }
78 |
79 | void vh_drag_desc(void* p, int level)
80 | {
81 | }
82 |
83 | void vh_drag_attach(ku_view_t* view, void (*on_event)(vh_drag_event_t))
84 | {
85 | assert(view->evt_han == NULL && view->evt_han_data == NULL);
86 |
87 | vh_drag_t* vh = CAL(sizeof(vh_drag_t), vh_drag_del, vh_drag_desc);
88 | vh->on_event = on_event;
89 |
90 | view->evt_han_data = vh;
91 | view->evt_han = vh_drag_evt;
92 | }
93 |
94 | void vh_drag_drag(ku_view_t* view, ku_view_t* item)
95 | {
96 | vh_drag_t* vh = view->evt_han_data;
97 |
98 | if (vh->dragged_view)
99 | {
100 | REL(vh->dragged_view);
101 | vh->dragged_view = NULL;
102 | }
103 | if (item)
104 | {
105 | vh->dragged_view = RET(item);
106 | }
107 | }
108 |
109 | #endif
110 |
--------------------------------------------------------------------------------
/src/kinetic_ui/handler/vh_key.c:
--------------------------------------------------------------------------------
1 | #ifndef vh_key_h
2 | #define vh_key_h
3 |
4 | #include "ku_view.c"
5 |
6 | typedef struct _vh_key_t vh_key_t;
7 |
8 | typedef struct _vh_key_event_t
9 | {
10 | ku_event_t ev;
11 | vh_key_t* vh;
12 | ku_view_t* view;
13 | } vh_key_event_t;
14 |
15 | struct _vh_key_t
16 | {
17 | void (*on_event)(vh_key_event_t event);
18 | };
19 |
20 | void vh_key_add(ku_view_t* view, void (*on_event)(vh_key_event_t));
21 |
22 | #endif
23 |
24 | #if __INCLUDE_LEVEL__ == 0
25 |
26 | int vh_key_evt(ku_view_t* view, ku_event_t ev)
27 | {
28 | if (ev.type == KU_EVENT_KEY_DOWN)
29 | {
30 | vh_key_t* vh = view->evt_han_data;
31 | vh_key_event_t event = {.ev = ev, .vh = vh, .view = view};
32 | if (vh->on_event)
33 | (*vh->on_event)(event);
34 | }
35 |
36 | return 0;
37 | }
38 |
39 | void vh_key_del(void* p)
40 | {
41 | }
42 |
43 | void vh_key_desc(void* p, int level)
44 | {
45 | printf("vh_key");
46 | }
47 |
48 | void vh_key_add(ku_view_t* view, void (*on_event)(vh_key_event_t))
49 | {
50 | assert(view->evt_han == NULL && view->evt_han_data == NULL);
51 |
52 | vh_key_t* vh = CAL(sizeof(vh_key_t), vh_key_del, vh_key_desc);
53 | vh->on_event = on_event;
54 |
55 | view->evt_han_data = vh;
56 | view->evt_han = vh_key_evt;
57 | }
58 |
59 | #endif
60 |
--------------------------------------------------------------------------------
/src/kinetic_ui/handler/vh_knob.c:
--------------------------------------------------------------------------------
1 | #ifndef vh_knob_h
2 | #define vh_knob_h
3 |
4 | #include "ku_view.c"
5 |
6 | void vh_knob_add(ku_view_t* view, void (*ratio_changed)(ku_view_t* view, float ratio));
7 |
8 | #endif
9 |
10 | #if __INCLUDE_LEVEL__ == 0
11 |
12 | #include "ku_draw.c"
13 | #include "tg_knob.c"
14 | #include
15 |
16 | typedef struct _vh_knob_t
17 | {
18 | float angle;
19 | char* id;
20 |
21 | void (*ratio_changed)(ku_view_t* view, float ratio);
22 | } vh_knob_t;
23 |
24 | int vh_knob_evt(ku_view_t* view, ku_event_t ev)
25 | {
26 | if (ev.type == KU_EVENT_MOUSE_DOWN || (ev.type == KU_EVENT_MOUSE_MOVE && ev.drag))
27 | {
28 | vh_knob_t* vh = view->evt_han_data;
29 |
30 | float dx = ev.x - (view->frame.global.x + view->frame.global.w / 2.0);
31 | float dy = ev.y - (view->frame.global.y + view->frame.global.h / 2.0);
32 | float angle = atan2(dy, dx);
33 | float r = sqrt(dx * dx + dy * dy);
34 |
35 | if (angle < 0)
36 | angle += 6.28;
37 |
38 | if (r < view->frame.global.w / 2.0)
39 | {
40 | tg_knob_set_angle(view, angle);
41 | (*vh->ratio_changed)(view, angle);
42 | }
43 | }
44 | else if (ev.type == KU_EVENT_SCROLL)
45 | {
46 | vh_knob_t* vh = view->evt_han_data;
47 | tg_knob_t* tg = view->tex_gen_data;
48 |
49 | float angle = tg->angle - ev.dy / 50.0;
50 |
51 | if (angle < 0)
52 | angle += 6.28;
53 |
54 | if (tg->angle < 3 * 3.14 / 2 && tg->angle > 3.14 && angle > 3 * 3.14 / 2)
55 | angle = tg->angle;
56 | if (tg->angle > 3 * 3.14 / 2 && tg->angle < 2 * 3.14 && angle < 3 * 3.14 / 2)
57 | angle = tg->angle;
58 |
59 | if (angle > 6.28)
60 | angle -= 6.28;
61 | tg_knob_set_angle(view, angle);
62 | (*vh->ratio_changed)(view, angle);
63 | }
64 |
65 | return 1;
66 | }
67 |
68 | void vh_knob_desc(void* p, int level)
69 | {
70 | printf("vh_knob");
71 | }
72 |
73 | void vh_knob_add(ku_view_t* view, void (*ratio_changed)(ku_view_t* view, float ratio))
74 | {
75 | assert(view->evt_han == NULL && view->evt_han_data == NULL);
76 |
77 | vh_knob_t* vh = CAL(sizeof(vh_knob_t), NULL, vh_knob_desc);
78 |
79 | vh->ratio_changed = ratio_changed;
80 |
81 | view->evt_han_data = vh;
82 | view->evt_han = vh_knob_evt;
83 | }
84 |
85 | #endif
86 |
--------------------------------------------------------------------------------
/src/kinetic_ui/handler/vh_roll.c:
--------------------------------------------------------------------------------
1 | #ifndef vh_roll_h
2 | #define vh_roll_h
3 |
4 | #include "ku_event.c"
5 | #include "ku_view.c"
6 |
7 | enum vh_roll_event_id
8 | {
9 | VH_ROLL_IN,
10 | VH_ROLL_OUT
11 | };
12 |
13 | typedef struct _vh_roll_t vh_roll_t;
14 |
15 | typedef struct _vh_roll_event_t
16 | {
17 | enum vh_roll_event_id id;
18 | vh_roll_t* vh;
19 | ku_view_t* view;
20 | } vh_roll_event_t;
21 |
22 | struct _vh_roll_t
23 | {
24 | char active;
25 | void (*on_event)(vh_roll_event_t);
26 | };
27 |
28 | void vh_roll_add(ku_view_t* view, void (*on_event)(vh_roll_event_t));
29 |
30 | #endif
31 |
32 | #if __INCLUDE_LEVEL__ == 0
33 |
34 | int vh_roll_evt(ku_view_t* view, ku_event_t ev)
35 | {
36 | if (ev.type == KU_EVENT_MOUSE_MOVE)
37 | {
38 | vh_roll_t* vh = view->evt_han_data;
39 | ku_rect_t frame = view->frame.global;
40 |
41 | if (!vh->active)
42 | {
43 | if (ev.x >= frame.x &&
44 | ev.x <= frame.x + frame.w &&
45 | ev.y >= frame.y &&
46 | ev.y <= frame.y + frame.h)
47 | {
48 | vh->active = 1;
49 |
50 | vh_roll_event_t event = {.id = VH_ROLL_IN, .view = view, .vh = vh};
51 | if (vh->on_event)
52 | (*vh->on_event)(event);
53 | }
54 | }
55 | }
56 | else if (ev.type == KU_EVENT_MOUSE_MOVE_OUT)
57 | {
58 | vh_roll_t* vh = view->evt_han_data;
59 | ku_rect_t frame = view->frame.global;
60 |
61 | if (vh->active)
62 | {
63 | if (ev.x < frame.x ||
64 | ev.x > frame.x + frame.w ||
65 | ev.y < frame.y ||
66 | ev.y > frame.y + frame.h)
67 | {
68 | vh->active = 0;
69 | vh_roll_event_t event = {.id = VH_ROLL_OUT, .view = view, .vh = vh};
70 | if (vh->on_event)
71 | (*vh->on_event)(event);
72 | }
73 | }
74 | }
75 |
76 | return 1;
77 | }
78 |
79 | void vh_roll_del(void* p)
80 | {
81 | }
82 |
83 | void vh_roll_desc(void* p, int level)
84 | {
85 | printf("vh_roll");
86 | }
87 |
88 | void vh_roll_add(ku_view_t* view, void (*on_event)(vh_roll_event_t))
89 | {
90 | assert(view->evt_han == NULL && view->evt_han_data == NULL);
91 |
92 | vh_roll_t* vh = CAL(sizeof(vh_roll_t), vh_roll_del, vh_roll_desc);
93 | vh->on_event = on_event;
94 |
95 | view->evt_han_data = vh;
96 | view->evt_han = vh_roll_evt;
97 | }
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/src/kinetic_ui/handler/vh_slider.c:
--------------------------------------------------------------------------------
1 | #ifndef vh_slider_h
2 | #define vh_slider_h
3 |
4 | #include "ku_view.c"
5 |
6 | typedef struct _vh_slider_t vh_slider_t;
7 |
8 | typedef struct _vh_slider_event_t
9 | {
10 | vh_slider_t* vh;
11 | ku_view_t* view;
12 | float ratio;
13 | } vh_slider_event_t;
14 |
15 | struct _vh_slider_t
16 | {
17 | float ratio;
18 | char enabled;
19 | void (*on_event)(vh_slider_event_t);
20 | };
21 |
22 | void vh_slider_add(ku_view_t* view, void (*on_event)(vh_slider_event_t));
23 | void vh_slider_set(ku_view_t* view, float ratio);
24 | float vh_slider_get_ratio(ku_view_t* view);
25 | void vh_slider_set_enabled(ku_view_t* view, int flag);
26 |
27 | #endif
28 |
29 | #if __INCLUDE_LEVEL__ == 0
30 |
31 | #include "vh_anim.c"
32 | #include
33 |
34 | int vh_slider_evt(ku_view_t* view, ku_event_t ev)
35 | {
36 | vh_slider_t* vh = view->evt_han_data;
37 |
38 | if (vh->enabled)
39 | {
40 | if (ev.type == KU_EVENT_MOUSE_DOWN || (ev.type == KU_EVENT_MOUSE_MOVE && ev.drag))
41 | {
42 | float dx = ev.x - view->frame.global.x;
43 | vh->ratio = dx / view->frame.global.w;
44 |
45 | ku_view_t* bar = view->views->data[0];
46 | ku_rect_t frame = bar->frame.local;
47 | frame.w = dx;
48 | ku_view_set_frame(bar, frame);
49 |
50 | vh_slider_event_t event = {.view = view, .ratio = vh->ratio, .vh = vh};
51 | if (vh->on_event)
52 | (*vh->on_event)(event);
53 | }
54 | else if (ev.type == KU_EVENT_SCROLL)
55 | {
56 | float ratio = vh->ratio - ev.dx / 50.0;
57 |
58 | if (ratio < 0)
59 | ratio = 0;
60 | if (ratio > 1)
61 | ratio = 1;
62 |
63 | vh->ratio = ratio;
64 | ku_view_t* bar = view->views->data[0];
65 | ku_rect_t frame = bar->frame.local;
66 | frame.w = view->frame.global.w * vh->ratio;
67 | ku_view_set_frame(bar, frame);
68 |
69 | vh_slider_event_t event = {.view = view, .ratio = vh->ratio, .vh = vh};
70 | if (vh->on_event)
71 | (*vh->on_event)(event);
72 | }
73 | }
74 |
75 | return 0;
76 | }
77 |
78 | void vh_slider_set(ku_view_t* view, float ratio)
79 | {
80 | vh_slider_t* vh = view->evt_han_data;
81 | vh->ratio = ratio;
82 | ku_view_t* bar = view->views->data[0];
83 | ku_rect_t frame = bar->frame.local;
84 | frame.w = view->frame.global.w * vh->ratio;
85 | ku_view_set_frame(bar, frame);
86 | }
87 |
88 | float vh_slider_get_ratio(ku_view_t* view)
89 | {
90 | vh_slider_t* vh = view->evt_han_data;
91 | return vh->ratio;
92 | }
93 |
94 | void vh_slider_desc(void* p, int level)
95 | {
96 | printf("vh_slider");
97 | }
98 |
99 | void vh_slider_del(void* p)
100 | {
101 | }
102 |
103 | void vh_slider_add(ku_view_t* view, void (*on_event)(vh_slider_event_t))
104 | {
105 | assert(view->evt_han == NULL && view->evt_han_data == NULL);
106 |
107 | vh_slider_t* vh = CAL(sizeof(vh_slider_t), vh_slider_del, vh_slider_desc);
108 | vh->on_event = on_event;
109 | vh->enabled = 1;
110 |
111 | view->evt_han_data = vh;
112 | view->evt_han = vh_slider_evt;
113 |
114 | ku_view_t* bar = view->views->data[0];
115 | vh_anim_add(bar, NULL, NULL);
116 | }
117 |
118 | void vh_slider_set_enabled(ku_view_t* view, int flag)
119 | {
120 | vh_slider_t* vh = view->evt_han_data;
121 |
122 | if (flag)
123 | {
124 | if (vh->enabled == 0)
125 | {
126 | ku_view_t* bar = view->views->data[0];
127 | vh_anim_alpha(bar, 0.3, 1.0, 10, AT_LINEAR);
128 | }
129 | }
130 | else
131 | {
132 | if (vh->enabled == 1)
133 | {
134 | ku_view_t* bar = view->views->data[0];
135 | vh_anim_alpha(bar, 1.0, 0.3, 10, AT_LINEAR);
136 | }
137 | }
138 |
139 | vh->enabled = flag;
140 | }
141 |
142 | #endif
143 |
--------------------------------------------------------------------------------
/src/kinetic_ui/handler/vh_touch.c:
--------------------------------------------------------------------------------
1 | #ifndef vh_touch_h
2 | #define vh_touch_h
3 |
4 | #include "ku_view.c"
5 |
6 | typedef struct _vh_touch_t vh_touch_t;
7 |
8 | enum vh_touch_event_id
9 | {
10 | VH_TOUCH_EVENT
11 | };
12 |
13 | typedef struct _vh_touch_event_t
14 | {
15 | enum vh_touch_event_id id;
16 | vh_touch_t* vh;
17 | ku_view_t* view;
18 | } vh_touch_event_t;
19 |
20 | struct _vh_touch_t
21 | {
22 | void (*on_event)(vh_touch_event_t);
23 | };
24 |
25 | void vh_touch_add(ku_view_t* view, void (*on_event)(vh_touch_event_t));
26 |
27 | #endif
28 |
29 | #if __INCLUDE_LEVEL__ == 0
30 |
31 | #include "ku_event.c"
32 |
33 | int vh_touch_evt(ku_view_t* view, ku_event_t ev)
34 | {
35 | if (ev.type == KU_EVENT_MOUSE_DOWN)
36 | {
37 | vh_touch_t* vh = view->evt_han_data;
38 | vh_touch_event_t event = {.id = VH_TOUCH_EVENT, .vh = vh, .view = view};
39 | if (vh->on_event)
40 | (*vh->on_event)(event);
41 | }
42 |
43 | return 0;
44 | }
45 |
46 | void vh_touch_del(void* p)
47 | {
48 | /* vh_touch_t* vh = p; */
49 | }
50 |
51 | void vh_touch_desc(void* p, int level)
52 | {
53 | printf("vh_touch");
54 | }
55 |
56 | void vh_touch_add(ku_view_t* view, void (*on_event)(vh_touch_event_t))
57 | {
58 | assert(view->evt_han == NULL && view->evt_han_data == NULL);
59 |
60 | vh_touch_t* vh = CAL(sizeof(vh_touch_t), vh_touch_del, vh_touch_desc);
61 | vh->on_event = on_event;
62 |
63 | view->evt_han = vh_touch_evt;
64 | view->evt_han_data = vh;
65 | }
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_css.c:
--------------------------------------------------------------------------------
1 | /*
2 | Kinetic UI CSS parser
3 | Does pretty dumb parsing, error handling should be improved
4 | */
5 |
6 | #ifndef ku_css_h
7 | #define ku_css_h
8 |
9 | /* TODO write tests */
10 |
11 | #include "mt_log.c"
12 | #include "mt_map.c"
13 | #include "mt_string.c"
14 | #include "mt_vector.c"
15 | #include
16 | #include
17 | #include
18 |
19 | typedef struct _css_range_t
20 | {
21 | uint32_t pos;
22 | uint32_t len;
23 | } css_range_t;
24 |
25 | typedef struct _prop_t
26 | {
27 | css_range_t class;
28 | css_range_t key;
29 | css_range_t value;
30 | } prop_t;
31 |
32 | mt_map_t* ku_css_new(char* path);
33 |
34 | #endif
35 |
36 | #if __INCLUDE_LEVEL__ == 0
37 |
38 | #include "mt_string_ext.c"
39 |
40 | uint32_t ku_css_count_props(char* css)
41 | {
42 | int t = 0; // tag index
43 | char* c = css;
44 | while (*c)
45 | {
46 | if (*c == ':')
47 | t++;
48 | c++;
49 | }
50 | return t;
51 | }
52 |
53 | void ku_css_analyze_classes(char* css, prop_t* props)
54 | {
55 | int start = -1;
56 | // char in_l = 0; // in line
57 | uint32_t index = 0;
58 | css_range_t class = {0};
59 | int in_str = 0;
60 | char* c = css;
61 | while (*c)
62 | {
63 | if (*c == '}' || *c == ' ' || *c == '\r' || *c == '\n')
64 | {
65 | if (c - css - 1 == start) start = c - css; // skip starting empty chars
66 | }
67 | else if (*c == '"') // class name
68 | {
69 | in_str = 1 - in_str;
70 | }
71 | else if (*c == '{') // class name
72 | {
73 | class.pos = start + 1;
74 | class.len = c - css - start - 2;
75 | while (*(css + class.pos + class.len) == ' ') class.len--;
76 | class.len++;
77 | start = c - css;
78 | }
79 | else if (*c == ':' && !in_str) // property name
80 | {
81 | props[index].class = class;
82 | props[index].key.pos = start + 1;
83 | props[index].key.len = c - css - start - 1;
84 | start = c - css;
85 | }
86 | else if (*c == ';') // value name
87 | {
88 | props[index].class = class;
89 | props[index].value.pos = start + 1;
90 | props[index].value.len = c - css - start - 1;
91 |
92 | start = c - css;
93 | index++;
94 | }
95 |
96 | c++;
97 | }
98 | }
99 |
100 | void ku_css_prop_desc(void* p, int level)
101 | {
102 | printf("html prop_t");
103 | }
104 |
105 | prop_t* ku_css_new_parse(char* css)
106 | {
107 | uint32_t cnt = ku_css_count_props(css);
108 | prop_t* props = CAL(sizeof(prop_t) * (cnt + 1), NULL, ku_css_prop_desc); // REL 1
109 |
110 | ku_css_analyze_classes(css, props);
111 |
112 | for (uint32_t i = 0; i < cnt; i++)
113 | {
114 | // prop_t p = props[i];
115 | // printf("extracted prop %.*s %.*s %.*s\n", p.class.len, css + p.class.pos, p.key.len, css + p.key.pos, p.value.len, css + p.value.pos);
116 | }
117 |
118 | return props;
119 | }
120 |
121 | mt_map_t* ku_css_new(char* filepath)
122 | {
123 | mt_map_t* styles = MNEW(); // REL 2
124 | char* css = mt_string_new_file(filepath); // REL 0
125 |
126 | if (css)
127 | {
128 | prop_t* view_styles = ku_css_new_parse(css); // REL 1
129 | prop_t* props = view_styles;
130 |
131 | while ((*props).class.len > 0)
132 | {
133 | prop_t t = *props;
134 | char* cls = CAL(sizeof(char) * t.class.len + 1, NULL, mt_string_describe); // REL 3
135 | char* key = CAL(sizeof(char) * t.key.len + 1, NULL, mt_string_describe); // REL 4
136 | char* val = CAL(sizeof(char) * t.value.len + 1, NULL, mt_string_describe); // REL 5
137 |
138 | memcpy(cls, css + t.class.pos, t.class.len);
139 | memcpy(key, css + t.key.pos, t.key.len);
140 | memcpy(val, css + t.value.pos, t.value.len);
141 |
142 | mt_map_t* style = MGET(styles, cls);
143 | if (style == NULL)
144 | {
145 | style = MNEW(); // REL 6
146 | MPUT(styles, cls, style);
147 | REL(style); // REL 6
148 | }
149 | MPUT(style, key, val);
150 | props += 1;
151 | REL(cls); // REL 3
152 | REL(key); // REL 4
153 | REL(val); // REL 5
154 | }
155 |
156 | REL(view_styles);
157 | REL(css);
158 | }
159 | else mt_log_error("Empty CSS descriptor");
160 |
161 | return styles;
162 | }
163 |
164 | #endif
165 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_event.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_event_h
2 | #define ku_event_h
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | enum evtype
9 | {
10 | KU_EVENT_EMPTY,
11 | KU_EVENT_FRAME,
12 | KU_EVENT_TIME,
13 | KU_EVENT_RESIZE,
14 | KU_EVENT_MOUSE_MOVE,
15 | KU_EVENT_MOUSE_DOWN,
16 | KU_EVENT_MOUSE_UP,
17 | KU_EVENT_MOUSE_MOVE_OUT,
18 | KU_EVENT_MOUSE_DOWN_OUT,
19 | KU_EVENT_MOUSE_UP_OUT,
20 | KU_EVENT_SCROLL,
21 | KU_EVENT_SCROLL_X_END,
22 | KU_EVENT_SCROLL_Y_END,
23 | KU_EVENT_KEY_DOWN,
24 | KU_EVENT_KEY_UP,
25 | KU_EVENT_TEXT,
26 | KU_EVENT_WINDOW_SHOWN,
27 | KU_EVENT_PINCH,
28 | KU_EVENT_HOLD_START,
29 | KU_EVENT_HOLD_END,
30 | KU_EVENT_STDIN,
31 | KU_EVENT_FOCUS,
32 | KU_EVENT_UNFOCUS,
33 | };
34 |
35 | typedef struct _ku_event_t
36 | {
37 | int type;
38 |
39 | /* poiniter properties */
40 |
41 | int x; // mouse coord x
42 | int y; // mouse coord y
43 |
44 | /* resize */
45 |
46 | int w; // resize width
47 | int h; // resize height
48 |
49 | /* scroll */
50 |
51 | float dx; // scroll x
52 | float dy; // scroll y
53 |
54 | /* pinch */
55 |
56 | float ratio; // pinch ratio
57 |
58 | /* mouse */
59 |
60 | int drag; // mouse drag
61 | int dclick; // double click
62 | int button; // mouse button id
63 |
64 | /* time */
65 |
66 | uint32_t time; // milliseconds since start
67 | struct timespec time_unix; // unix timestamp
68 | float time_frame; // elapsed time since last frame
69 | uint32_t frame; // actual frame count
70 |
71 | /* keyboard */
72 |
73 | uint32_t keycode;
74 | int repeat; // key event is coming from repeat
75 |
76 | int ctrl_down; // modifiers
77 | int shift_down; // modifiers
78 |
79 | char text[8];
80 |
81 | /* window */
82 |
83 | void* window;
84 |
85 | } ku_event_t;
86 |
87 | void ku_event_write(FILE* file, ku_event_t ev);
88 | ku_event_t ku_event_read(FILE* file);
89 |
90 | #endif
91 |
92 | #if __INCLUDE_LEVEL__ == 0
93 |
94 | #include "mt_log.c"
95 |
96 | /* frame type x y w h dx dy ratio drag dclick button time time_frame keycode repeat ctrl_down shift_down text */
97 | char* ku_print_format = "%i %i %i %i %i %i %f %f %f %i %i %i %u %f %u %i %i %i '%s'\n";
98 | char* ku_scan_format = "%i %i %i %i %i %i %f %f %f %i %i %i %u %f %u %i %i %i '%[^']'\n";
99 |
100 | void ku_event_write(FILE* file, ku_event_t ev)
101 | {
102 | fprintf(
103 | file,
104 | ku_print_format,
105 | ev.frame,
106 | ev.type,
107 | ev.x,
108 | ev.y,
109 | ev.w,
110 | ev.h,
111 | ev.dx,
112 | ev.dy,
113 | ev.ratio,
114 | ev.drag,
115 | ev.dclick,
116 | ev.button,
117 | ev.time,
118 | ev.time_frame,
119 | ev.keycode,
120 | ev.repeat,
121 | ev.ctrl_down,
122 | ev.shift_down,
123 | ev.text[0] == '\0' ? "T" : ev.text);
124 | }
125 |
126 | ku_event_t ku_event_read(FILE* file)
127 | {
128 | ku_event_t ev = {0};
129 | int res = fscanf(
130 | file,
131 | ku_scan_format,
132 | &ev.frame,
133 | &ev.type,
134 | &ev.x,
135 | &ev.y,
136 | &ev.w,
137 | &ev.h,
138 | &ev.dx,
139 | &ev.dy,
140 | &ev.ratio,
141 | &ev.drag,
142 | &ev.dclick,
143 | &ev.button,
144 | &ev.time,
145 | &ev.time_frame,
146 | &ev.keycode,
147 | &ev.repeat,
148 | &ev.ctrl_down,
149 | &ev.shift_down,
150 | &ev.text);
151 |
152 | if (res < 0)
153 | mt_log_error("Couldn't scanf file");
154 |
155 | return ev;
156 | }
157 |
158 | #endif
159 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_fontconfig.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_fontconfig_h
2 | #define ku_fontconfig_h
3 |
4 | char* ku_fontconfig_path(char* face_desc);
5 | void ku_fontconfig_delete();
6 |
7 | #endif
8 |
9 | #if __INCLUDE_LEVEL__ == 0
10 |
11 | #include
12 | #ifdef __linux__
13 | #include
14 | #endif
15 |
16 | // #define _POSIX_C_SOURCE 200112L
17 | #include "mt_map.c"
18 | #include "mt_memory.c"
19 | #include "mt_string.c"
20 | #include
21 | #include
22 |
23 | mt_map_t* ku_fontconfig_cache = NULL;
24 |
25 | char* ku_fontconfig_path(char* face_desc)
26 | {
27 | char* filename = NULL;
28 | if (face_desc)
29 | {
30 | if (ku_fontconfig_cache == NULL)
31 | ku_fontconfig_cache = MNEW();
32 | filename = MGET(ku_fontconfig_cache, face_desc);
33 |
34 | if (filename == NULL)
35 | {
36 | char buff[PATH_MAX];
37 | filename = mt_string_new_cstring(""); // REL 0
38 | char* command = mt_string_new_format(80, "fc-match \"%s\" --format=%%{file}", face_desc); // REL 1
39 | FILE* pipe = popen(command, "r"); // CLOSE 0
40 | while (fgets(buff, sizeof(buff), pipe) != NULL) filename = mt_string_append(filename, buff);
41 | pclose(pipe); // CLOSE 0
42 | REL(command); // REL 1
43 |
44 | MPUTR(ku_fontconfig_cache, face_desc, filename);
45 | }
46 | }
47 | return filename;
48 | }
49 |
50 | void ku_fontconfig_delete()
51 | {
52 | if (ku_fontconfig_cache) REL(ku_fontconfig_cache);
53 | ku_fontconfig_cache = NULL;
54 | }
55 |
56 | #endif
57 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_gen_html.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_gen_html_h
2 | #define ku_gen_html_h
3 |
4 | #include "mt_vector.c"
5 |
6 | void ku_gen_html_parse(char* htmlpath, mt_vector_t* views);
7 |
8 | #endif
9 |
10 | #if __INCLUDE_LEVEL__ == 0
11 |
12 | #include "ku_html.c"
13 | #include "ku_view.c"
14 | #include "mt_log.c"
15 | #include "mt_string_ext.c"
16 |
17 | void ku_gen_html_parse(char* htmlpath, mt_vector_t* views)
18 | {
19 | char* html = mt_string_new_file(htmlpath); // REL 0
20 |
21 | if (html != NULL)
22 | {
23 | tag_t* tags = ku_html_new(html); // REL 1
24 | tag_t* head = tags;
25 |
26 | while ((*tags).len > 0)
27 | {
28 | tag_t t = *tags;
29 | if (t.id.len > 0)
30 | {
31 | // extract id
32 | char* id = CAL(sizeof(char) * t.id.len + 1, NULL, mt_string_describe); // REL 0
33 | memcpy(id, html + t.id.pos + 1, t.id.len);
34 | ku_view_t* view = ku_view_new(id, (ku_rect_t){0}); // REL 1
35 |
36 | if (t.level > 0)
37 | {
38 | // add to parent
39 | ku_view_t* parent = views->data[t.parent];
40 | ku_view_add_subview(parent, view);
41 | }
42 |
43 | if (t.class.len > 0)
44 | {
45 | // store css classes
46 | char* class = CAL(sizeof(char) * t.class.len + 1, NULL, mt_string_describe); // REL 0
47 | memcpy(class, html + t.class.pos + 1, t.class.len);
48 | ku_view_set_class(view, class);
49 | REL(class);
50 | }
51 |
52 | if (t.type.len > 0)
53 | {
54 | // store html stype
55 | char* type = CAL(sizeof(char) * t.type.len + 1, NULL, mt_string_describe); // REL 2
56 | memcpy(type, html + t.type.pos + 1, t.type.len);
57 | ku_view_set_type(view, type);
58 | REL(type); // REL 2
59 | }
60 |
61 | if (t.text.len > 0)
62 | {
63 | // store html stype
64 | char* text = CAL(sizeof(char) * t.text.len + 1, NULL, mt_string_describe); // REL 2
65 | memcpy(text, html + t.text.pos + 1, t.text.len);
66 | ku_view_set_text(view, text);
67 | REL(text); // REL 2
68 | }
69 |
70 | if (t.script.len > 0)
71 | {
72 | // store html stype
73 | char* script = CAL(sizeof(char) * t.script.len + 1, NULL, mt_string_describe); // REL 2
74 | memcpy(script, html + t.script.pos + 1, t.script.len);
75 | ku_view_set_script(view, script);
76 | REL(script); // REL 2
77 | }
78 |
79 | VADD(views, view);
80 |
81 | REL(id); // REL 0
82 | REL(view); // REL 1
83 | }
84 | else
85 | {
86 | static int divcnt = 0;
87 | char* divid = mt_string_new_format(10, "div%i", divcnt++);
88 | // idless view, probably
89 | ku_view_t* view = ku_view_new(divid, (ku_rect_t){0});
90 | VADD(views, view);
91 | REL(view);
92 | REL(divid);
93 | }
94 | tags += 1;
95 | }
96 |
97 | // cleanup
98 |
99 | REL(head); // REL 1
100 | REL(html); // REL 0
101 | }
102 | else mt_log_error("No HTML description");
103 | }
104 |
105 | #endif
106 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_gen_textstyle.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_gen_textstyle_h
2 | #define ku_gen_textstyle_h
3 |
4 | #include "ku_text.c"
5 | #include "ku_view.c"
6 |
7 | textstyle_t ku_gen_textstyle_parse(ku_view_t* view);
8 |
9 | #endif
10 |
11 | #if __INCLUDE_LEVEL__ == 0
12 |
13 | #include "ku_fontconfig.c"
14 | #include
15 |
16 | textstyle_t ku_gen_textstyle_parse(ku_view_t* view)
17 | {
18 | textstyle_t style = {0};
19 |
20 | char* font = ku_fontconfig_path(view->style.font_family);
21 | if (font) strcpy(style.font, font);
22 |
23 | style.size = view->style.font_size > 0 ? view->style.font_size : 15;
24 |
25 | style.align = view->style.text_align;
26 | style.valign = view->style.vertical_align;
27 | /* style.autosize = */
28 | style.multiline = view->style.word_wrap == 1;
29 | style.line_height = view->style.line_height;
30 |
31 | style.margin = view->style.margin;
32 | if (view->style.margin_left < INT_MAX) style.margin_left = view->style.margin_left;
33 | if (view->style.margin_right < INT_MAX) style.margin_right = view->style.margin_right;
34 | if (view->style.margin_top < INT_MAX) style.margin_top = view->style.margin_top;
35 | if (view->style.margin_bottom < INT_MAX) style.margin_bottom = view->style.margin_bottom;
36 |
37 | style.textcolor = view->style.color;
38 | style.backcolor = view->style.background_color;
39 |
40 | return style;
41 | }
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_gen_type.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_gen_type_h
2 | #define ku_gen_type_h
3 |
4 | #include "mt_vector.c"
5 | #include "vh_button.c"
6 | #include "vh_slider.c"
7 |
8 | void ku_gen_type_apply(mt_vector_t* views, void (*button_event)(vh_button_event_t), void (*slider_event)(vh_slider_event_t));
9 |
10 | #endif
11 |
12 | #if __INCLUDE_LEVEL__ == 0
13 |
14 | #include "ku_view.c"
15 | #include "tg_css.c"
16 | #include "tg_text.c"
17 |
18 | void ku_gen_type_apply(mt_vector_t* views, void (*button_event)(vh_button_event_t), void (*slider_event)(vh_slider_event_t))
19 | {
20 | for (size_t index = 0; index < views->length; index++)
21 | {
22 | ku_view_t* view = views->data[index];
23 |
24 | if (view->type && strcmp(view->type, "label") == 0)
25 | {
26 | tg_text_add(view);
27 | tg_text_set1(view, view->text);
28 | }
29 | else if (view->style.background_color > 0 || view->style.border_color > 0)
30 | {
31 | tg_css_add(view);
32 | }
33 | else if (strlen(view->style.background_image) > 0)
34 | {
35 | tg_css_add(view);
36 | }
37 |
38 | if (view->type && strcmp(view->type, "button") == 0)
39 | {
40 | vh_button_add(view, VH_BUTTON_NORMAL, button_event);
41 | }
42 | else if (view->type && strcmp(view->type, "slider") == 0)
43 | {
44 | vh_slider_add(view, slider_event);
45 | }
46 | }
47 | }
48 |
49 | #endif
50 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_html.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_html_h
2 | #define ku_html_h
3 |
4 | /* TODO write tests */
5 |
6 | #include "mt_string.c"
7 | #include "mt_vector.c"
8 | #include
9 | #include
10 | #include
11 |
12 | typedef struct _html_range_t
13 | {
14 | uint32_t pos;
15 | uint32_t len;
16 | } html_range_t;
17 |
18 | typedef struct _tag_t
19 | {
20 | uint32_t pos;
21 | uint32_t len;
22 |
23 | uint32_t level;
24 | uint32_t parent;
25 |
26 | html_range_t id;
27 | html_range_t type;
28 | html_range_t text;
29 | html_range_t class;
30 | html_range_t script;
31 | } tag_t;
32 |
33 | tag_t* ku_html_new(char* path);
34 |
35 | #endif
36 |
37 | #if __INCLUDE_LEVEL__ == 0
38 |
39 | uint32_t ku_html_count_tags(char* html)
40 | {
41 | uint32_t t = 0; // tag index
42 | char* c = html;
43 | int in_tag = 0;
44 | int in_comm = 0;
45 | while (*c)
46 | {
47 | if (*c == '<')
48 | {
49 | if (!in_comm)
50 | {
51 | in_tag = 1;
52 | }
53 | }
54 | else if (*c == '!')
55 | {
56 | if (in_tag)
57 | {
58 | if (*(c - 1) == '<') in_comm += 1;
59 | }
60 | }
61 | else if (*c == '>')
62 | {
63 | if (in_comm)
64 | {
65 | if (*(c - 1) == '-') in_comm -= 1;
66 |
67 | if (!in_comm)
68 | {
69 | in_tag = 0;
70 | }
71 | }
72 | else if (in_tag)
73 | {
74 | in_tag = 0;
75 | t++;
76 | }
77 | }
78 | c++;
79 | }
80 |
81 | return t;
82 | }
83 |
84 | void ku_html_extract_tags(char* html, tag_t* tags)
85 | {
86 | uint32_t t = 0; // tag index
87 | uint32_t i = 0; // char index
88 | char* c = html;
89 | int in_tag = 0;
90 | int in_comm = 0;
91 | while (*c)
92 | {
93 | if (*c == '<')
94 | {
95 | if (!in_comm)
96 | {
97 | tags[t].pos = i;
98 | in_tag = 1;
99 | }
100 | }
101 | else if (*c == '!')
102 | {
103 | if (in_tag)
104 | {
105 | if (*(c - 1) == '<') in_comm += 1;
106 | }
107 | }
108 | else if (*c == '>')
109 | {
110 | if (in_comm)
111 | {
112 | if (*(c - 1) == '-') in_comm -= 1;
113 |
114 | if (!in_comm)
115 | {
116 | in_tag = 0;
117 | }
118 | }
119 | else if (in_tag)
120 | {
121 | tags[t].len = i - tags[t].pos + 1;
122 | in_tag = 0;
123 | // printf("storing %i tag %.*s\n", t, tags[t].len, html + tags[t].pos);
124 | t++;
125 | }
126 | }
127 | i++;
128 | c++;
129 | }
130 | }
131 |
132 | html_range_t ku_html_extract_string(char* str, uint32_t pos, uint32_t len)
133 | {
134 | int start = 0;
135 | int end = 0;
136 | int in = 0;
137 | for (uint32_t i = pos; i < pos + len; i++)
138 | {
139 | char c = str[i];
140 | if (c == '"')
141 | {
142 | if (!in)
143 | {
144 | in = 1;
145 | start = i;
146 | }
147 | else
148 | {
149 | in = 0;
150 | end = i;
151 | break;
152 | }
153 | }
154 | }
155 | if (!in)
156 | return ((html_range_t){.pos = start, .len = end - start - 1});
157 | else
158 | return ((html_range_t){0});
159 | }
160 |
161 | html_range_t ku_html_extract_value(tag_t tag, char* key, char* html)
162 | {
163 | char* start = strstr(html + tag.pos, key);
164 | uint32_t len = start - (html + tag.pos);
165 |
166 | if (len < tag.len)
167 | {
168 | html_range_t range = ku_html_extract_string(html, start - html, tag.len);
169 | return range;
170 | }
171 | return ((html_range_t){0});
172 | }
173 |
174 | void ku_html_analyze_tags(char* html, tag_t* tags, uint32_t count)
175 | {
176 | int l = 0; // level
177 | for (uint32_t i = 0; i < count; i++)
178 | {
179 | tags[i].level = l++;
180 |
181 | int ii = i;
182 | while (ii-- > 0)
183 | {
184 | if (tags[ii].level == tags[i].level - 1)
185 | {
186 | tags[i].parent = ii;
187 | break;
188 | }
189 | }
190 |
191 | tags[i].id = ku_html_extract_value(tags[i], "id=\"", html);
192 | tags[i].type = ku_html_extract_value(tags[i], "type=\"", html);
193 | tags[i].text = ku_html_extract_value(tags[i], "text=\"", html);
194 | tags[i].class = ku_html_extract_value(tags[i], "class=\"", html);
195 | tags[i].script = ku_html_extract_value(tags[i], "script=\"", html);
196 |
197 | // tag_t t = tags[i];
198 |
199 | if (html[tags[i].pos + 1] == '/')
200 | l -= 2; //
201 | if (html[tags[i].pos + tags[i].len - 2] == '/' || html[tags[i].pos + tags[i].len - 2] == '-')
202 | l -= 1; // />
203 | }
204 | }
205 |
206 | void ku_html_tag_describe(void* p, int level)
207 | {
208 | printf("html tag_t");
209 | }
210 |
211 | tag_t* ku_html_new(char* html)
212 | {
213 | uint32_t cnt = ku_html_count_tags(html);
214 | tag_t* tags = CAL(sizeof(tag_t) * (cnt + 1), NULL, ku_html_tag_describe); // REL 0
215 |
216 | ku_html_extract_tags(html, tags);
217 | ku_html_analyze_tags(html, tags, cnt);
218 |
219 | /* for (int i = 0; i < cnt; i++) */
220 | /* { */
221 | /* tag_t t = tags[i]; */
222 | /* printf("ind %i tag %.*s lvl %i par %i\n", i, t.len, html + t.pos, t.level, t.parent); */
223 | /* } */
224 |
225 | return tags;
226 | }
227 |
228 | #endif
229 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_png.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_png_h
2 | #define ku_png_h
3 |
4 | #include "ku_bitmap.c"
5 | #include
6 |
7 | void ku_png_get_size(char* path, int* width, int* height);
8 | void ku_png_load_into(char* path, ku_bitmap_t* bitmap);
9 | void ku_png_write(char* filename, ku_bitmap_t* bitmap);
10 |
11 | #endif
12 |
13 | #if __INCLUDE_LEVEL__ == 0
14 |
15 | #define PNG_DEBUG 3
16 | #include "ku_draw.c"
17 | #include "mt_log.c"
18 | #include "mt_memory.c"
19 | #include
20 | #include
21 |
22 | void ku_png_get_size(char* path, int* width, int* height)
23 | {
24 | unsigned char header[8];
25 |
26 | /* open file and test for it being a png */
27 | FILE* fp = fopen(path, "rb");
28 |
29 | if (fp)
30 | {
31 | int res = fread(header, 1, 8, fp);
32 | if (res == 0) mt_log_error("fread error");
33 |
34 | if (png_sig_cmp(header, 0, 8) == 0)
35 | {
36 | png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
37 |
38 | if (png_ptr)
39 | {
40 | png_infop info_ptr = png_create_info_struct(png_ptr);
41 |
42 | if (info_ptr)
43 | {
44 | if (setjmp(png_jmpbuf(png_ptr)) == 0)
45 | {
46 | png_init_io(png_ptr, fp);
47 | png_set_sig_bytes(png_ptr, 8);
48 |
49 | png_read_info(png_ptr, info_ptr);
50 |
51 | *width = png_get_image_width(png_ptr, info_ptr);
52 | *height = png_get_image_height(png_ptr, info_ptr);
53 | }
54 | else mt_log_error("png init io failed");
55 |
56 | png_destroy_info_struct(png_ptr, &info_ptr);
57 | }
58 | else mt_log_error("png_create_info_struct failed");
59 |
60 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
61 | }
62 | else mt_log_error("png_create_read_struct failed");
63 | }
64 | else mt_log_error("Not a PNG file");
65 |
66 | fclose(fp);
67 | }
68 | else mt_log_error("Cannot open %s for read", path);
69 | }
70 |
71 | void ku_png_load_into(char* path, ku_bitmap_t* bitmap)
72 | {
73 | unsigned char header[8];
74 |
75 | /* open file and test for it being a png */
76 | FILE* fp = fopen(path, "rb");
77 |
78 | if (fp)
79 | {
80 | int res = fread(header, 1, 8, fp);
81 | if (res == 0) mt_log_error("fread error");
82 |
83 | if (png_sig_cmp(header, 0, 8) == 0)
84 | {
85 | png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
86 |
87 | if (png_ptr)
88 | {
89 | png_infop info_ptr = png_create_info_struct(png_ptr);
90 |
91 | if (info_ptr)
92 | {
93 | if (setjmp(png_jmpbuf(png_ptr)) == 0)
94 | {
95 | png_init_io(png_ptr, fp);
96 | png_set_sig_bytes(png_ptr, 8);
97 |
98 | png_read_info(png_ptr, info_ptr);
99 |
100 | int width = png_get_image_width(png_ptr, info_ptr);
101 | int height = png_get_image_height(png_ptr, info_ptr);
102 |
103 | png_bytep* row_pointers;
104 |
105 | png_read_update_info(png_ptr, info_ptr);
106 |
107 | /* read file */
108 | if (setjmp(png_jmpbuf(png_ptr)) == 0)
109 | {
110 | int y;
111 | size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
112 |
113 | row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
114 |
115 | for (y = 0; y < height; y++) row_pointers[y] = (png_byte*) malloc(rowbytes);
116 |
117 | png_read_image(png_ptr, row_pointers);
118 |
119 | ku_bitmap_t* rawbm = ku_bitmap_new(width, height);
120 |
121 | for (y = 0; y < height; y++) memcpy((uint8_t*) rawbm->data + y * width * 4, row_pointers[y], rowbytes);
122 |
123 | for (y = 0; y < height; y++) free(row_pointers[y]);
124 | free(row_pointers);
125 |
126 | if (bitmap->w == rawbm->w && bitmap->h == rawbm->h)
127 | ku_draw_insert(bitmap, rawbm, 0, 0);
128 | else
129 | ku_draw_scale(rawbm, bitmap);
130 |
131 | REL(rawbm);
132 | }
133 | else mt_log_error("Cannot read PNG");
134 | }
135 | else mt_log_error("png init io failed");
136 |
137 | png_destroy_info_struct(png_ptr, &info_ptr);
138 | }
139 | else mt_log_error("png_create_info_struct failed");
140 |
141 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
142 | }
143 | else mt_log_error("png_create_read_struct failed");
144 | }
145 | else mt_log_error("Not a PNG file");
146 |
147 | fclose(fp);
148 | }
149 | else mt_log_error("Cannot open %s for read", path);
150 | }
151 |
152 | void ku_png_write(char* filename, ku_bitmap_t* bitmap)
153 | {
154 | int y;
155 |
156 | FILE* fp = fopen(filename, "wb");
157 |
158 | if (fp)
159 | {
160 | png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
161 |
162 | if (png_ptr)
163 | {
164 | png_infop info_ptr = png_create_info_struct(png_ptr);
165 |
166 | if (info_ptr)
167 | {
168 | if (!setjmp(png_jmpbuf(png_ptr)))
169 | {
170 | png_init_io(png_ptr, fp);
171 |
172 | png_set_IHDR(
173 | png_ptr,
174 | info_ptr,
175 | bitmap->w,
176 | bitmap->h,
177 | 8,
178 | PNG_COLOR_TYPE_RGBA,
179 | PNG_INTERLACE_NONE,
180 | PNG_COMPRESSION_TYPE_DEFAULT,
181 | PNG_FILTER_TYPE_DEFAULT);
182 | png_write_info(png_ptr, info_ptr);
183 |
184 | size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
185 |
186 | png_bytep* row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * bitmap->h);
187 |
188 | for (y = 0; y < bitmap->h; y++) row_pointers[y] = (png_byte*) malloc(rowbytes);
189 |
190 | for (y = 0; y < bitmap->h; y++) memcpy(row_pointers[y], (uint8_t*) bitmap->data + y * bitmap->w * 4, rowbytes);
191 |
192 | if (!row_pointers) abort();
193 |
194 | png_write_image(png_ptr, row_pointers);
195 | png_write_end(png_ptr, NULL);
196 |
197 | for (y = 0; y < bitmap->h; y++) free(row_pointers[y]);
198 | free(row_pointers);
199 | }
200 | else mt_log_error("cannot set jump");
201 | }
202 | else mt_log_error("Cannot create info struct");
203 |
204 | png_destroy_write_struct(&png_ptr, &info_ptr);
205 | }
206 | else mt_log_error("png create write failed");
207 |
208 | fclose(fp);
209 | }
210 | else mt_log_error("Cannot open %s for read", filename);
211 | }
212 |
213 | #endif
214 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_recorder.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_recorder_h
2 | #define ku_recorder_h
3 |
4 | #include "ku_event.c"
5 |
6 | void ku_recorder_init(void (*update)(ku_event_t));
7 | void ku_recorder_destroy();
8 | void ku_recorder_update(ku_event_t ev);
9 | void ku_recorder_record(char* path);
10 | void ku_recorder_replay(char* path);
11 |
12 | #endif
13 |
14 | #if __INCLUDE_LEVEL__ == 0
15 |
16 | #include "mt_vector.c"
17 | #include
18 |
19 | enum ku_recorder_mode_t
20 | {
21 | KU_REC_MODE_NORMAL,
22 | KU_REC_MODE_RECORD,
23 | KU_REC_MODE_REPLAY,
24 | };
25 |
26 | struct ku_recorder_t
27 | {
28 | size_t index;
29 | FILE* file;
30 | mt_vector_t* eventqueue;
31 | void (*update)(ku_event_t);
32 | enum ku_recorder_mode_t mode;
33 | } kurec;
34 |
35 | void ku_recorder_init(void (*update)(ku_event_t))
36 | {
37 | kurec.mode = KU_REC_MODE_NORMAL;
38 | kurec.update = update;
39 | kurec.eventqueue = VNEW();
40 | }
41 |
42 | void ku_recorder_record(char* path)
43 | {
44 | kurec.mode = KU_REC_MODE_RECORD;
45 | FILE* file = fopen(path, "w");
46 | if (!file) printf("evrec recorder : cannot open file %s\n", path);
47 | kurec.file = file;
48 | }
49 |
50 | void ku_recorder_replay(char* path)
51 | {
52 | kurec.mode = KU_REC_MODE_REPLAY;
53 | FILE* file = fopen(path, "r");
54 | if (!file)
55 | printf("evrec player : cannot open file %s\n", path);
56 |
57 | kurec.file = file;
58 |
59 | while (1)
60 | {
61 | ku_event_t ev = ku_event_read(file);
62 | VADDR(kurec.eventqueue, HEAP(ev));
63 | if (feof(file))
64 | break;
65 | }
66 |
67 | printf("%li events read\n", kurec.eventqueue->length);
68 | }
69 |
70 | void ku_recorder_destroy()
71 | {
72 | if (kurec.file) fclose(kurec.file);
73 | if (kurec.eventqueue) REL(kurec.eventqueue);
74 | }
75 |
76 | void ku_recorder_update_record(ku_event_t ev)
77 | {
78 | /* normalize floats for deterministic movements during record/replay */
79 | ev.dx = floor(ev.dx * 10000) / 10000;
80 | ev.dy = floor(ev.dy * 10000) / 10000;
81 | ev.ratio = floor(ev.ratio * 10000) / 10000;
82 | ev.time_frame = floor(ev.time_frame * 10000) / 10000;
83 |
84 | if (ev.type == KU_EVENT_FRAME || ev.type == KU_EVENT_TIME || ev.type == KU_EVENT_WINDOW_SHOWN)
85 | {
86 | /* record and send waiting events */
87 | for (size_t index = 0; index < kurec.eventqueue->length; index++)
88 | {
89 | ku_event_t* event = (ku_event_t*) kurec.eventqueue->data[index];
90 | event->frame = ev.frame;
91 |
92 | ku_event_write(kurec.file, *event);
93 |
94 | (*kurec.update)(*event);
95 | }
96 |
97 | mt_vector_reset(kurec.eventqueue);
98 |
99 | /* send frame event */
100 | (*kurec.update)(ev);
101 | }
102 | else
103 | {
104 | /* queue event */
105 | void* event = HEAP(ev);
106 | VADDR(kurec.eventqueue, event);
107 | }
108 | }
109 |
110 | void ku_recorder_update_replay(ku_event_t ev)
111 | {
112 | if (ev.type == KU_EVENT_FRAME || ev.type == KU_EVENT_WINDOW_SHOWN)
113 | {
114 | while (kurec.index < kurec.eventqueue->length)
115 | {
116 | ku_event_t* event = kurec.eventqueue->data[kurec.index];
117 |
118 | if (event->frame < ev.frame)
119 | {
120 | kurec.index++;
121 | (*kurec.update)(*event);
122 | }
123 | else break;
124 | }
125 |
126 | (*kurec.update)(ev);
127 | }
128 | }
129 |
130 | void ku_recorder_update(ku_event_t ev)
131 | {
132 | if (kurec.mode == KU_REC_MODE_NORMAL) (*kurec.update)(ev);
133 | else if (kurec.mode == KU_REC_MODE_RECORD) ku_recorder_update_record(ev);
134 | else if (kurec.mode == KU_REC_MODE_REPLAY) ku_recorder_update_replay(ev);
135 | }
136 |
137 | #endif
138 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_rect.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_rect_h
2 | #define ku_rect_h
3 |
4 | /* TODO write tests */
5 |
6 | typedef struct _ku_rect_t ku_rect_t;
7 | struct _ku_rect_t
8 | {
9 | float x;
10 | float y;
11 | float w;
12 | float h;
13 | };
14 |
15 | int ku_rect_equals(ku_rect_t r1, ku_rect_t r2);
16 | ku_rect_t ku_rect_add(ku_rect_t r1, ku_rect_t r2);
17 | ku_rect_t ku_rect_is(ku_rect_t l, ku_rect_t r);
18 | void ku_rect_describe(ku_rect_t rect);
19 |
20 | #endif
21 |
22 | #if __INCLUDE_LEVEL__ == 0
23 |
24 | #include
25 |
26 | #define VMIN(X, Y) (((X) < (Y)) ? (X) : (Y))
27 | #define VMAX(X, Y) (((X) > (Y)) ? (X) : (Y))
28 |
29 | int ku_rect_equals(ku_rect_t r1, ku_rect_t r2)
30 | {
31 | return (r1.x == r2.x && r1.y == r2.y && r1.w == r2.w && r1.h == r2.h);
32 | }
33 |
34 | ku_rect_t ku_rect_add(ku_rect_t r1, ku_rect_t r2)
35 | {
36 | if (r1.w == 0 || r1.h == 0) return r2;
37 | if (r2.w == 0 || r2.h == 0) return r1;
38 |
39 | ku_rect_t res;
40 |
41 | res.x = VMIN(r1.x, r2.x);
42 | res.y = VMIN(r1.y, r2.y);
43 |
44 | float r1cx = r1.x + r1.w;
45 | float r1cy = r1.y + r1.h;
46 | float r2cx = r2.x + r2.w;
47 | float r2cy = r2.y + r2.h;
48 |
49 | res.w = r1cx < r2cx ? (r2cx - res.x) : (r1cx - res.x);
50 | res.h = r1cy < r2cy ? (r2cy - res.y) : (r1cy - res.y);
51 |
52 | return res;
53 | }
54 |
55 | ku_rect_t ku_rect_is(ku_rect_t l, ku_rect_t r)
56 | {
57 | ku_rect_t f = {0};
58 | if (!(l.x + l.w < r.x || r.x + r.w < l.x || l.y + l.h < r.y || r.y + r.h < l.y))
59 | {
60 | f.x = VMAX(l.x, r.x);
61 | f.y = VMAX(l.y, r.y);
62 | f.w = VMIN(r.x + r.w - f.x, l.x + l.w - f.x);
63 | f.h = VMIN(r.y + r.h - f.y, l.y + l.h - f.y);
64 | }
65 |
66 | return f;
67 | }
68 |
69 | void ku_rect_describe(ku_rect_t rect)
70 | {
71 | printf("%f %f %f %f\n", rect.x, rect.y, rect.w, rect.h);
72 | }
73 |
74 | #endif
75 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_renderer_egl.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_renderer_egl_h
2 | #define ku_renderer_egl_h
3 |
4 | #include "ku_bitmap.c"
5 | #include "ku_rect.c"
6 | #include "mt_vector.c"
7 |
8 | void ku_renderer_egl_init(int max_device_width, int max_device_height);
9 | void ku_renderer_egl_destroy();
10 | void ku_renderer_egl_render(mt_vector_t* views, ku_bitmap_t* bitmap, ku_rect_t dirty);
11 | void ku_renderer_egl_screenshot(ku_bitmap_t* bitmap, char* path);
12 |
13 | #endif
14 |
15 | #if __INCLUDE_LEVEL__ == 0
16 |
17 | #include "ku_gl.c"
18 | #include "ku_png.c"
19 | #include "ku_view.c"
20 | #include "mt_time.c"
21 |
22 | void ku_renderer_egl_init(int max_device_width, int max_device_height)
23 | {
24 | ku_gl_init(max_device_width, max_device_height);
25 |
26 | glClearColor(0.0, 0.0, 0.0, 1.0);
27 | }
28 |
29 | void ku_renderer_egl_destroy()
30 | {
31 | ku_gl_destroy();
32 | }
33 |
34 | void ku_renderer_egl_render(mt_vector_t* views, ku_bitmap_t* bitmap, ku_rect_t dirty)
35 | {
36 | /* cut out dirty rect */
37 |
38 | ku_gl_add_textures(views, 0);
39 | ku_gl_add_vertexes(views);
40 |
41 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
42 |
43 | /* we need to keep nested masks in mind */
44 |
45 | static ku_rect_t masks[32] = {0};
46 | static int maski = 0;
47 |
48 | masks[0] = (ku_rect_t){0, 0, bitmap->w, bitmap->h};
49 | dirty = masks[0];
50 |
51 | for (size_t i = 0; i < views->length; i++)
52 | {
53 | ku_view_t* view = views->data[i];
54 |
55 | if (view->style.masked)
56 | {
57 | dirty = view->frame.global;
58 | if (view->style.shadow_blur > 0)
59 | {
60 | dirty.x -= view->style.shadow_blur;
61 | dirty.y -= view->style.shadow_blur;
62 | dirty.w += 2 * view->style.shadow_blur;
63 | dirty.h += 2 * view->style.shadow_blur;
64 | }
65 |
66 | maski++;
67 | masks[maski] = dirty;
68 | /* printf("%s masked, dirty %f %f %f %f\n", view->id, dirty.x, dirty.y, dirty.w, dirty.h); */
69 | }
70 |
71 | if (view->texture.bitmap || view->texture.full)
72 | {
73 | bmr_t mask = (bmr_t){(int) dirty.x, (int) dirty.y, (int) (dirty.x + dirty.w), (int) (dirty.y + dirty.h)};
74 |
75 | if (view->frame.region.w > -1 && view->frame.region.h > -1)
76 | {
77 | ku_rect_t rect = view->frame.global;
78 |
79 | bmr_t srcmsk = {(int) rect.x, (int) rect.y, (int) (rect.x + rect.w), (int) (rect.y + rect.h)};
80 |
81 | srcmsk.x += view->frame.region.x;
82 | srcmsk.y += view->frame.region.y;
83 | srcmsk.z = srcmsk.x + view->frame.region.w;
84 | srcmsk.w = srcmsk.y + view->frame.region.h;
85 |
86 | mask = srcmsk;
87 |
88 | if (srcmsk.x != srcmsk.z)
89 | ku_gl_render_quad(bitmap, i, mask);
90 | }
91 | else
92 | {
93 | ku_gl_render_quad(bitmap, i, mask);
94 | }
95 | }
96 |
97 | if (view->style.unmask)
98 | {
99 | maski--;
100 | dirty = masks[maski];
101 | }
102 | }
103 |
104 | /* render with dirty rects, has artifacts because of double buffering, will work on it later, won't be much more efficient though */
105 |
106 | /* masks[0] = dirty; */
107 |
108 | /* draw views */
109 |
110 | /* for (size_t i = 0; i < views->length; i++) */
111 | /* { */
112 | /* ku_view_t* view = views->data[i]; */
113 |
114 | /* if (view->style.masked) */
115 | /* { */
116 | /* dirty = ku_rect_is(masks[maski], view->frame.global); */
117 | /* maski++; */
118 | /* masks[maski] = dirty; */
119 | /* /\* printf("%s masked, dirty %f %f %f %f\n", view->id, dirty.x, dirty.y, dirty.w, dirty.h); *\/ */
120 | /* } */
121 |
122 | /* if (view->texture.bitmap) */
123 | /* { */
124 | /* ku_rect_t rect = view->frame.global; */
125 |
126 | /* bmr_t dstmsk = ku_bitmap_is( */
127 | /* (bmr_t){(int) dirty.x, (int) dirty.y, (int) (dirty.x + dirty.w), (int) (dirty.y + dirty.h)}, */
128 | /* (bmr_t){0, 0, bitmap->w, bitmap->h}); */
129 |
130 | /* bmr_t srcmsk = {(int) rect.x, (int) rect.y, (int) (rect.x + rect.w), (int) (rect.y + rect.h)}; */
131 |
132 | /* /\* if there is a region to draw, modify source mask *\/ */
133 |
134 | /* if (view->frame.region.w > 0 && view->frame.region.h > 0) */
135 | /* { */
136 | /* srcmsk.x += view->frame.region.x; */
137 | /* srcmsk.y += view->frame.region.y; */
138 | /* srcmsk.z = srcmsk.x + view->frame.region.w; */
139 | /* srcmsk.w = srcmsk.y + view->frame.region.h; */
140 | /* } */
141 |
142 | /* dstmsk = ku_bitmap_is(dstmsk, srcmsk); */
143 |
144 | /* ku_gl_render_quad(bitmap, i, dstmsk); */
145 | /* } */
146 |
147 | /* if (view->style.unmask) */
148 | /* { */
149 | /* maski--; */
150 | /* dirty = masks[maski]; */
151 | /* } */
152 | /* } */
153 | }
154 |
155 | void ku_renderer_egl_screenshot(ku_bitmap_t* bm, char* path)
156 | {
157 | ku_bitmap_t* bitmap = ku_bitmap_new(bm->w, bm->h);
158 | ku_gl_save_framebuffer(bitmap);
159 |
160 | ku_bitmap_t* flipped = ku_bitmap_new(bm->w, bm->h);
161 | for (int y = 0; y < bitmap->h; y++)
162 | {
163 | int src_y = bitmap->h - y - 1;
164 | memcpy(flipped->data + y * bitmap->w * 4, bitmap->data + src_y * bitmap->w * 4, bitmap->w * 4);
165 | }
166 |
167 | ku_png_write(path, flipped);
168 |
169 | REL(flipped);
170 | REL(bitmap);
171 | }
172 |
173 | #endif
174 |
--------------------------------------------------------------------------------
/src/kinetic_ui/ku_renderer_soft.c:
--------------------------------------------------------------------------------
1 | #ifndef ku_renderer_software_h
2 | #define ku_renderer_software_h
3 |
4 | #include "ku_bitmap.c"
5 | #include "ku_rect.c"
6 | #include "mt_vector.c"
7 |
8 | void ku_renderer_software_render(mt_vector_t* views, ku_bitmap_t* bitmap, ku_rect_t dirty);
9 | void ku_renderer_soft_screenshot(ku_bitmap_t* bitmap, char* path);
10 |
11 | #endif
12 |
13 | #if __INCLUDE_LEVEL__ == 0
14 |
15 | #include "ku_png.c"
16 | #include "ku_view.c"
17 | #include "mt_time.c"
18 |
19 | void ku_renderer_software_render(mt_vector_t* views, ku_bitmap_t* bitmap, ku_rect_t dirty)
20 | {
21 | /* cut out dirty rect */
22 |
23 | /* ku_bitmap_cut(&mmfm.window->bitmap, (int) sum.x, (int) sum.y, (int) sum.w, (int) sum.h); */
24 |
25 | /* draw dirty rect for debugging */
26 |
27 | /* ku_bitmap_blend_rect(bitmap, (int) dirty.x, (int) dirty.y, (int) dirty.w, (int) dirty.h, 0x55FF0000); */
28 | /* ku_wayland_draw_window(mmfm.window, 0, 0, mmfm.window->width, mmfm.window->height); */
29 |
30 | /* we need to keep nested masks in mind */
31 |
32 | static ku_rect_t masks[32] = {0};
33 | static int maski = 0;
34 |
35 | masks[0] = dirty;
36 |
37 | /* draw views into bitmap */
38 |
39 | for (size_t i = 0; i < views->length; i++)
40 | {
41 | ku_view_t* view = views->data[i];
42 |
43 | if (view->style.masked)
44 | {
45 | dirty = ku_rect_is(masks[maski], view->frame.global);
46 | maski++;
47 | masks[maski] = dirty;
48 | /* printf("%s masked, dirty %f %f %f %f\n", view->id, dirty.x, dirty.y, dirty.w, dirty.h); */
49 | }
50 |
51 | if (view->texture.bitmap)
52 | {
53 | ku_rect_t rect = view->frame.global;
54 |
55 | bmr_t dstmsk = ku_bitmap_is(
56 | (bmr_t){(int) dirty.x, (int) dirty.y, (int) (dirty.x + dirty.w), (int) (dirty.y + dirty.h)},
57 | (bmr_t){0, 0, bitmap->w, bitmap->h});
58 |
59 | bmr_t srcmsk = {0, 0, view->texture.bitmap->w, view->texture.bitmap->h};
60 |
61 | /* if there is a region to draw, modify source mask */
62 |
63 | if (view->frame.region.w > -1 && view->frame.region.h > -1)
64 | {
65 | srcmsk.x += view->frame.region.x;
66 | srcmsk.y += view->frame.region.y;
67 | srcmsk.z = srcmsk.x + view->frame.region.w;
68 | srcmsk.w = srcmsk.y + view->frame.region.h;
69 | }
70 |
71 | /* draw with shadow blur outlets in mind */
72 |
73 | if (view->texture.transparent == 0 || i == 0)
74 | {
75 | ku_bitmap_insert(
76 | bitmap,
77 | dstmsk,
78 | view->texture.bitmap,
79 | srcmsk,
80 | rect.x - view->style.shadow_blur,
81 | rect.y - view->style.shadow_blur);
82 | }
83 | else
84 | {
85 | if (view->texture.alpha == 1.0)
86 | {
87 | ku_bitmap_blend(
88 | bitmap,
89 | dstmsk,
90 | view->texture.bitmap,
91 | srcmsk,
92 | rect.x - view->style.shadow_blur,
93 | rect.y - view->style.shadow_blur);
94 | }
95 | else
96 | {
97 | ku_bitmap_blend_with_alpha(
98 | bitmap,
99 | dstmsk,
100 | view->texture.bitmap,
101 | srcmsk,
102 | rect.x - view->style.shadow_blur,
103 | rect.y - view->style.shadow_blur,
104 | (255 - (int) (view->texture.alpha * 255.0)));
105 | }
106 | }
107 | }
108 |
109 | if (view->style.unmask)
110 | {
111 | maski--;
112 | dirty = masks[maski];
113 | }
114 | }
115 | }
116 |
117 | void ku_renderer_soft_screenshot(ku_bitmap_t* bitmap, char* path)
118 | {
119 | ku_png_write(path, bitmap);
120 | }
121 |
122 | #endif
123 |
--------------------------------------------------------------------------------
/src/kinetic_ui/texture/tg_css.c:
--------------------------------------------------------------------------------
1 | /*
2 | CSS texture generator
3 | Generates texture based on css style
4 | */
5 |
6 | #ifndef texgen_css_h
7 | #define texgen_css_h
8 |
9 | #include "ku_bitmap.c"
10 | #include "ku_view.c"
11 |
12 | typedef struct _tg_css_t
13 | {
14 | char* id;
15 | char* path;
16 | ku_bitmap_t* bitmap;
17 | } tg_bitmap_t;
18 |
19 | void tg_css_add(ku_view_t* view);
20 |
21 | #endif
22 |
23 | #if __INCLUDE_LEVEL__ == 0
24 |
25 | #include "ku_draw.c"
26 | #include "ku_png.c"
27 | #include "mt_log.c"
28 | #include "mt_string.c"
29 |
30 | int tg_css_gen(ku_view_t* view)
31 | {
32 | if (view->frame.local.w >= 1.0 &&
33 | view->frame.local.h >= 1.0)
34 | {
35 | if (strlen(view->style.background_image) > 0)
36 | {
37 | ku_bitmap_t* bm = view->texture.bitmap;
38 |
39 | if (bm == NULL ||
40 | bm->w != (int) view->frame.local.w ||
41 | bm->h != (int) view->frame.local.h)
42 | {
43 | bm = ku_bitmap_new((int) view->frame.local.w, (int) view->frame.local.h); // REL 0
44 | ku_view_set_texture_bmp(view, bm);
45 | REL(bm);
46 | }
47 |
48 | ku_png_load_into(view->style.background_image, bm);
49 |
50 | view->texture.transparent = 1;
51 | view->texture.changed = 0;
52 | view->texture.ready = 1;
53 | }
54 | else if (view->style.background_color)
55 | {
56 | uint32_t color = view->style.background_color;
57 |
58 | if ((color & 0xFF) < 0xFF || view->style.shadow_blur > 0 || view->style.border_radius > 0 || view->style.border_color > 0)
59 | view->texture.transparent = 1;
60 | else
61 | view->texture.transparent = 0;
62 |
63 | float w = view->frame.local.w + 2 * view->style.shadow_blur;
64 | float h = view->frame.local.h + 2 * view->style.shadow_blur;
65 |
66 | ku_bitmap_t* bm = view->texture.bitmap;
67 |
68 | if (bm == NULL ||
69 | bm->w != (int) w ||
70 | bm->h != (int) h)
71 | {
72 | bm = ku_bitmap_new((int) w, (int) h); // REL 0
73 | ku_view_set_texture_bmp(view, bm);
74 | REL(bm);
75 | }
76 |
77 | ku_bitmap_reset(bm);
78 |
79 | if (color > 0)
80 | ku_draw_rounded_rect(bm, 0, 0, w, h, view->style.border_radius, view->style.shadow_blur, color, view->style.shadow_color);
81 |
82 | if (view->style.border_width > 0)
83 | {
84 | ku_draw_border(
85 | bm,
86 | 0 + view->style.shadow_blur,
87 | 0 + view->style.shadow_blur,
88 | w - 2 * view->style.shadow_blur,
89 | h - 2 * view->style.shadow_blur,
90 | view->style.border_radius,
91 | view->style.border_width,
92 | view->style.border_color);
93 | }
94 |
95 | view->texture.changed = 1;
96 | view->texture.ready = 1;
97 | }
98 | }
99 |
100 | return 1;
101 | }
102 |
103 | void tg_css_add(ku_view_t* view)
104 | {
105 | if (view->tex_gen != NULL)
106 | mt_log_debug("Text generator already exist for view, cannot create a new one : %s", view->id);
107 | else
108 | {
109 | view->tex_gen = tg_css_gen;
110 | }
111 | }
112 |
113 | #endif
114 |
--------------------------------------------------------------------------------
/src/kinetic_ui/texture/tg_knob.c:
--------------------------------------------------------------------------------
1 |
2 | #ifndef texgen_knob_h
3 | #define texgen_knob_h
4 |
5 | #include "ku_view.c"
6 |
7 | typedef struct _tg_knob_t
8 | {
9 | float angle;
10 | ku_bitmap_t* back;
11 | ku_bitmap_t* fore;
12 | } tg_knob_t;
13 |
14 | void tg_knob_add(ku_view_t* view);
15 | void tg_knob_set_angle(ku_view_t* view, float angle);
16 |
17 | #endif
18 |
19 | #if __INCLUDE_LEVEL__ == 0
20 |
21 | #include "ku_draw.c"
22 |
23 | int tg_knob_gen(ku_view_t* view)
24 | {
25 | tg_knob_t* tg = view->tex_gen_data;
26 |
27 | if (view->frame.local.w > 0 && view->frame.local.h > 0)
28 | {
29 |
30 | float dist0 = 5 * view->style.scale;
31 | float dist1 = 27 * view->style.scale;
32 | float dist8 = 28 * view->style.scale;
33 | float dist2 = 31 * view->style.scale;
34 | float dist3 = 35 * view->style.scale;
35 |
36 | if (view->texture.bitmap == NULL && view->frame.local.w > 0 && view->frame.local.h > 0)
37 | {
38 | ku_bitmap_t* bmp = ku_bitmap_new(view->frame.local.w, view->frame.local.h); // REL 0
39 | tg->back = ku_bitmap_new(view->frame.local.w, view->frame.local.h); // REL 1
40 | tg->fore = ku_bitmap_new(view->frame.local.w, view->frame.local.h); // REL 2
41 |
42 | uint32_t basecol = 0x454545FF;
43 | uint32_t outercol = 0x343434FF;
44 | uint32_t centercol = 0x676767FF;
45 | uint32_t shadowcol = 0xABABAB0A;
46 |
47 | /* ku_draw_arc_grad(tg->back, */
48 | /* (view->frame.local.w - 1.0) / 2.0, */
49 | /* (view->frame.local.h - 1.0) / 2.0, */
50 | /* (view->frame.local.w / 2.0) - 3.0, */
51 | /* (view->frame.local.w / 2.0), */
52 | /* 0, */
53 | /* 3.14 * 2, */
54 | /* 0x00000044, */
55 | /* 0); */
56 |
57 | ku_draw_arc_grad(tg->back, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, 0, (view->frame.local.w / 2.0) - dist0, 0, 3.14 * 2, basecol, basecol);
58 | ku_draw_arc_grad(tg->back, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist3, 0, 3.14 * 2, outercol, outercol);
59 | ku_draw_arc_grad(tg->back, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, (view->frame.local.w / 2.0) - dist0, (view->frame.local.w / 2.0) - 2.0, 0, 3.14 * 2, shadowcol, 0x00000000);
60 |
61 | ku_draw_arc_grad(tg->fore, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist2, 0, 3.14 * 2, shadowcol, 0);
62 | ku_draw_arc_grad(tg->fore, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, 0, dist8, 0, 3.14 * 2, centercol, centercol);
63 | ku_view_set_texture_bmp(view, bmp);
64 |
65 | REL(bmp); // REL 0
66 | }
67 |
68 | if (tg->angle < 0)
69 | tg->angle += 6.28;
70 |
71 | ku_draw_insert(view->texture.bitmap, tg->back, 0, 0);
72 |
73 | if (tg->angle > 3.14 * 3 / 2)
74 | {
75 | ku_draw_arc_grad(view->texture.bitmap, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist3, 3.14 * 3 / 2, tg->angle, 0x999999FF, 0x999999FF);
76 | }
77 | else
78 | {
79 | ku_draw_arc_grad(view->texture.bitmap, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist3, 3.14 * 3 / 2, 6.28, 0x999999FF, 0x999999FF);
80 | ku_draw_arc_grad(view->texture.bitmap, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist3, 0, tg->angle, 0x999999FF, 0x999999FF);
81 | }
82 |
83 | ku_draw_blend_argb(view->texture.bitmap, 0, 0, tg->fore);
84 | view->texture.changed = 1;
85 | view->texture.ready = 1;
86 | }
87 |
88 | return 1;
89 | }
90 |
91 | void tg_knob_del(void* p)
92 | {
93 | tg_knob_t* tg = p;
94 | if (tg->back) REL(tg->back);
95 | if (tg->fore) REL(tg->fore);
96 | }
97 |
98 | void tg_knob_desc(void* p, int level)
99 | {
100 | printf("tg_knob");
101 | }
102 |
103 | void tg_knob_add(ku_view_t* view)
104 | {
105 | assert(view->tex_gen == NULL);
106 |
107 | tg_knob_t* tg = CAL(sizeof(tg_knob_t), tg_knob_del, tg_knob_desc);
108 | tg->angle = 3 * 3.14 / 2;
109 |
110 | view->tex_gen_data = tg;
111 | view->tex_gen = tg_knob_gen;
112 | }
113 |
114 | void tg_knob_set_angle(ku_view_t* view, float angle)
115 | {
116 | tg_knob_t* tg = view->tex_gen_data;
117 |
118 | tg->angle = angle;
119 | view->texture.ready = 0; // force rerender
120 | }
121 |
122 | #endif
123 |
--------------------------------------------------------------------------------
/src/kinetic_ui/texture/tg_scaledimg.c:
--------------------------------------------------------------------------------
1 | /*
2 | CSS texture generator
3 | Generates texture based on css style
4 | */
5 |
6 | #ifndef texgen_scaledimg_h
7 | #define texgen_scaledimg_h
8 |
9 | #include "ku_bitmap.c"
10 | #include "ku_view.c"
11 |
12 | typedef struct _tg_scaledimg_t
13 | {
14 | int w;
15 | int h;
16 | } tg_scaledimg_t;
17 |
18 | void tg_scaledimg_add(ku_view_t* view, int w, int h);
19 | int tg_scaledimg_gen(ku_view_t* view);
20 | void tg_scaledimg_set_content_size(ku_view_t* view, int w, int h);
21 |
22 | #endif
23 |
24 | #if __INCLUDE_LEVEL__ == 0
25 |
26 | #include "ku_draw.c"
27 | #include "mt_string.c"
28 |
29 | int tg_scaledimg_gen(ku_view_t* view)
30 | {
31 | tg_scaledimg_t* gen = view->tex_gen_data;
32 | ku_bitmap_t* bm = view->texture.bitmap;
33 |
34 | /* just resize texture bitmap with the view */
35 |
36 | if (bm == NULL ||
37 | bm->w != (int) gen->w ||
38 | bm->h != (int) gen->h)
39 | {
40 | bm = ku_bitmap_new_aligned((int) gen->w, (int) gen->h, 16); // REL 0
41 |
42 | ku_view_set_texture_bmp(view, bm);
43 |
44 | ku_draw_rect(bm, 0, 0, bm->w, bm->h, 0x00000000, 0);
45 |
46 | REL(bm);
47 | }
48 |
49 | view->texture.ready = 1;
50 |
51 | return 1;
52 | }
53 |
54 | void tg_scaledimg_set_content_size(ku_view_t* view, int w, int h)
55 | {
56 | tg_scaledimg_t* gen = view->tex_gen_data;
57 |
58 | gen->w = w;
59 | gen->h = h;
60 | }
61 |
62 | void tg_scaledimg_add(ku_view_t* view, int w, int h)
63 | {
64 | assert(view->tex_gen == NULL);
65 |
66 | tg_scaledimg_t* gen = CAL(sizeof(tg_scaledimg_t), NULL, NULL);
67 | gen->w = w;
68 | gen->h = h;
69 |
70 | view->tex_gen_data = gen;
71 | view->tex_gen = tg_scaledimg_gen;
72 | }
73 |
74 | #endif
75 |
--------------------------------------------------------------------------------
/src/kinetic_ui/texture/tg_text.c:
--------------------------------------------------------------------------------
1 | /*
2 | Text texture generator
3 | Shows text in view
4 | */
5 |
6 | #ifndef texgen_text_h
7 | #define texgen_text_h
8 |
9 | #include "ku_text.c"
10 | #include "ku_view.c"
11 |
12 | typedef struct _tg_text_t
13 | {
14 | char* text;
15 | float scale;
16 | textstyle_t style;
17 | } tg_text_t;
18 |
19 | void tg_text_add(ku_view_t* view);
20 | void tg_text_set(ku_view_t* view, char* text, textstyle_t style);
21 | void tg_text_set1(ku_view_t* view, char* text);
22 | char* tg_text_get(ku_view_t* view);
23 | void tg_text_set_style(ku_view_t* view, textstyle_t style);
24 |
25 | #endif
26 |
27 | #if __INCLUDE_LEVEL__ == 0
28 |
29 | #include "ku_bitmap.c"
30 | #include "ku_draw.c"
31 | #include "ku_gen_textstyle.c"
32 | #include "mt_string.c"
33 | #include "tg_css.c"
34 |
35 | int tg_text_index = 0;
36 |
37 | int tg_text_gen(ku_view_t* view)
38 | {
39 | tg_text_t* gen = view->tex_gen_data;
40 | if (view->frame.local.w > 0 && view->frame.local.h > 0)
41 | {
42 | if (gen->scale != view->style.scale)
43 | {
44 | float ratio;
45 | if (gen->scale == 0.0)
46 | ratio = view->style.scale;
47 | else
48 | ratio = view->style.scale / gen->scale;
49 | gen->style.size *= ratio;
50 | gen->scale = view->style.scale;
51 | }
52 |
53 | ku_bitmap_t* fontmap = ku_bitmap_new((int) view->frame.local.w, (int) view->frame.local.h); // REL 0
54 | textstyle_t style = gen->style;
55 |
56 | if ((style.textcolor & 0xFF) < 0xFF || (style.backcolor & 0xFF) < 0xFF)
57 | view->texture.transparent = 1;
58 | else
59 | view->texture.transparent = 0;
60 |
61 | if ((gen->text != NULL) && strlen(gen->text) > 0)
62 | {
63 | ku_text_render(gen->text, style, fontmap);
64 | }
65 | else
66 | {
67 | ku_draw_rect(fontmap, 0, 0, fontmap->w, fontmap->h, style.backcolor, 0);
68 | }
69 |
70 | ku_view_set_texture_bmp(view, fontmap);
71 |
72 | REL(fontmap); // REL 0
73 | }
74 |
75 | return 1;
76 | }
77 |
78 | void tg_text_del(void* p)
79 | {
80 | tg_text_t* gen = p;
81 | if (gen->text) REL(gen->text);
82 | }
83 |
84 | void tg_text_desc(void* p, int level)
85 | {
86 | printf("tg_text");
87 | }
88 |
89 | void tg_text_add(ku_view_t* view)
90 | {
91 | assert(view->tex_gen == NULL);
92 |
93 | tg_text_t* gen = CAL(sizeof(tg_text_t), tg_text_del, tg_text_desc);
94 |
95 | gen->text = NULL; // REL 1
96 | gen->scale = view->style.scale;
97 | gen->style = ku_gen_textstyle_parse(view);
98 |
99 | view->tex_gen_data = gen;
100 | view->tex_gen = tg_text_gen;
101 | }
102 |
103 | void tg_text_set1(ku_view_t* view, char* text)
104 | {
105 | tg_text_t* gen = view->tex_gen_data;
106 |
107 | if (gen->text) REL(gen->text);
108 | if (text) gen->text = mt_string_new_cstring(text);
109 |
110 | view->texture.ready = 0;
111 | }
112 |
113 | void tg_text_set(ku_view_t* view, char* text, textstyle_t style)
114 | {
115 | tg_text_t* gen = view->tex_gen_data;
116 |
117 | if (gen->text) REL(gen->text);
118 | if (text) gen->text = mt_string_new_cstring(text);
119 |
120 | gen->style = style;
121 | gen->style.size *= gen->scale;
122 |
123 | view->texture.ready = 0;
124 | }
125 |
126 | void tg_text_set_style(ku_view_t* view, textstyle_t style)
127 | {
128 | tg_text_t* gen = view->tex_gen_data;
129 |
130 | gen->style = style;
131 | gen->style.size *= gen->scale;
132 | view->texture.ready = 0;
133 | }
134 |
135 | char* tg_text_get(ku_view_t* view)
136 | {
137 | tg_text_t* gen = view->tex_gen_data;
138 | return gen->text;
139 | }
140 |
141 | #endif
142 |
--------------------------------------------------------------------------------
/src/mt_core/mt_channel.c:
--------------------------------------------------------------------------------
1 | /*
2 | One-way non-locking communication channel between threads
3 | If mtch_send returns 0, channel is full, send data again later
4 | If mtch_recv returns 0, channel is empty
5 | */
6 |
7 | #ifndef mt_channel_h
8 | #define mt_channel_h
9 |
10 | #include "mt_memory.c"
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | typedef struct mt_channel_t mt_channel_t;
18 | struct mt_channel_t
19 | {
20 | char* flags;
21 | void** boxes;
22 |
23 | uint32_t size;
24 | uint32_t rpos; // read position
25 | uint32_t wpos; // write position
26 | };
27 |
28 | mt_channel_t* mt_channel_new(uint32_t size);
29 | void mt_channel_del(void* pointer);
30 | char mt_channel_send(mt_channel_t* ch, void* data);
31 | void* mt_channel_recv(mt_channel_t* ch);
32 |
33 | #endif
34 |
35 | #if __INCLUDE_LEVEL__ == 0
36 |
37 | void mt_channel_del(void* pointer)
38 | {
39 | assert(pointer != NULL);
40 |
41 | mt_channel_t* ch = pointer;
42 |
43 | REL(ch->flags);
44 | REL(ch->boxes);
45 | }
46 |
47 | void mt_channel_describe(void* p, int level)
48 | {
49 | mt_channel_t* ch = p;
50 | printf("mt_channel, size %u read pos %u write pos %u", ch->size, ch->rpos, ch->wpos);
51 | }
52 |
53 | void mt_channel_describe_flags(void* p, int level)
54 | {
55 | printf("mt_channel flags");
56 | }
57 |
58 | void mt_channel_describe_boxes(void* p, int level)
59 | {
60 | printf("mt_channel boxes");
61 | }
62 |
63 | mt_channel_t* mt_channel_new(uint32_t size)
64 | {
65 | mt_channel_t* ch = CAL(sizeof(mt_channel_t), mt_channel_del, mt_channel_describe);
66 |
67 | ch->flags = CAL(sizeof(char) * size, NULL, mt_channel_describe_flags);
68 | ch->boxes = CAL(sizeof(void*) * size, NULL, mt_channel_describe_boxes);
69 | ch->size = size;
70 | ch->rpos = 0;
71 | ch->wpos = 0;
72 |
73 | return ch;
74 | }
75 |
76 | char mt_channel_send(mt_channel_t* ch, void* data)
77 | {
78 | assert(ch != NULL);
79 | assert(data != NULL);
80 |
81 | // wait for the box to get empty
82 |
83 | if (ch->flags[ch->wpos] == 0)
84 | {
85 | /* swap these rows to cause a race condition and a failing test */
86 | ch->boxes[ch->wpos] = data; // first store data
87 | ch->flags[ch->wpos] = 1; // then set flag, it doesn't have to be atomic, only the last bit counts
88 |
89 | ch->wpos += 1; // increment write index, doesn't have to be atomic, this thread uses it only
90 | if (ch->wpos == ch->size)
91 | ch->wpos = 0;
92 |
93 | return 1;
94 | }
95 |
96 | return 0;
97 | }
98 |
99 | void* mt_channel_recv(mt_channel_t* ch)
100 | {
101 | assert(ch != NULL);
102 |
103 | if (ch->flags[ch->rpos] == 1)
104 | {
105 | void* result = ch->boxes[ch->rpos];
106 |
107 | ch->boxes[ch->rpos] = NULL; // empty box
108 | ch->flags[ch->rpos] = 0; // set flag, it doesn't have to be atomic, only the last bit counts
109 |
110 | ch->rpos += 1; // increment read index, it doesn't have to be atomic, this thread uses it only
111 |
112 | if (ch->rpos == ch->size)
113 | ch->rpos = 0;
114 |
115 | return result;
116 | }
117 |
118 | return NULL;
119 | }
120 | #endif
121 |
--------------------------------------------------------------------------------
/src/mt_core/mt_log.c:
--------------------------------------------------------------------------------
1 | #ifndef _mt_log_h
2 | #define _mt_log_h
3 |
4 | #include
5 |
6 | typedef enum
7 | {
8 | MT_LOG_DEBUG = 0,
9 | MT_LOG_INFO = 1,
10 | MT_LOG_WARN = 2,
11 | MT_LOG_ERROR = 3,
12 | } mt_log_importance;
13 |
14 | void mt_log(mt_log_importance importance, const char* file, int line, const char* fmt, ...);
15 | void mt_log_set_level(mt_log_importance importance);
16 | int mt_log_get_level();
17 | void mt_log_inc_verbosity(void);
18 | void mt_log_use_colors(bool use_colors);
19 | void mt_log_set_file_column(int column);
20 |
21 | #define mt_log_debug(...) mt_log(MT_LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
22 | #define mt_log_info(...) mt_log(MT_LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
23 | #define mt_log_warn(...) mt_log(MT_LOG_WARN, __FILE__, __LINE__, __VA_ARGS__)
24 | #define mt_log_error(...) mt_log(MT_LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
25 |
26 | #define mt_log_level_debug() mt_log_set_level(MT_LOG_DEBUG);
27 | #define mt_log_level_info() mt_log_set_level(MT_LOG_INFO);
28 | #define mt_log_level_warn() mt_log_set_level(MT_LOG_WARN);
29 | #define mt_log_level_error() mt_log_set_level(MT_LOG_ERROR);
30 |
31 | #endif
32 |
33 | #if __INCLUDE_LEVEL__ == 0
34 |
35 | #define COLOR_RESET "\x1B[0m"
36 | #define COLOR_WHITE "\x1B[1;37m"
37 | #define COLOR_BLACK "\x1B[0;30m"
38 | #define COLOR_BLUE "\x1B[0;34m"
39 | #define COLOR_LIGHT_BLUE "\x1B[1;34m"
40 | #define COLOR_GREEN "\x1B[0;32m"
41 | #define COLOR_LIGHT_GREEN "\x1B[1;32m"
42 | #define COLOR_CYAN "\x1B[0;36m"
43 | #define COLOR_LIGHT_CYAN "\x1B[1;36m"
44 | #define COLOR_RED "\x1B[0;31m"
45 | #define COLOR_LIGHT_RED "\x1B[1;31m"
46 | #define COLOR_PURPLE "\x1B[0;35m"
47 | #define COLOR_LIGHT_PURPLE "\x1B[1;35m"
48 | #define COLOR_BROWN "\x1B[0;33m"
49 | #define COLOR_YELLOW "\x1B[1;33m"
50 | #define COLOR_GRAY "\x1B[0;30m"
51 | #define COLOR_LIGHT_GRAY "\x1B[0;37m"
52 |
53 | #define __USE_POSIX199309 1
54 | /* #define _POSIX_C_SOURCE 199506L */
55 |
56 | #include
57 | #include
58 | #include
59 | #include
60 | #include
61 | #include
62 | #include
63 | #include
64 | #include
65 |
66 | static mt_log_importance min_importance_to_log = MT_LOG_WARN;
67 |
68 | static bool use_colors = false;
69 | static int file_col = 100;
70 |
71 | static const char* verbosity_names[] = {
72 | "DEBUG",
73 | "INFO",
74 | "WARN",
75 | "ERROR",
76 | };
77 |
78 | static const char* verbosity_colors[] = {
79 | COLOR_LIGHT_CYAN,
80 | COLOR_GREEN,
81 | COLOR_YELLOW,
82 | COLOR_LIGHT_RED,
83 | };
84 |
85 | void mt_log(const mt_log_importance importance, const char* file, const int line, const char* fmt, ...)
86 | {
87 | if (importance < min_importance_to_log)
88 | {
89 | return;
90 | }
91 |
92 | struct timespec ts;
93 | if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
94 | {
95 | fprintf(stdout, "clock_gettime() failed: %s\n", strerror(errno));
96 | ts.tv_sec = 0;
97 | ts.tv_nsec = 0;
98 | }
99 |
100 | struct tm* my_tm = localtime(&ts.tv_sec);
101 |
102 | if (use_colors)
103 | {
104 | fprintf(
105 | stdout,
106 | "%s%-5s%s ",
107 | verbosity_colors[importance],
108 | verbosity_names[importance],
109 | COLOR_RESET);
110 | }
111 | else
112 | {
113 | fprintf(stdout, "%-5s ", verbosity_names[importance]);
114 | }
115 |
116 | va_list args;
117 | va_start(args, fmt);
118 | vfprintf(stdout, fmt, args);
119 | va_end(args);
120 |
121 | if (use_colors)
122 | {
123 | fprintf(
124 | stdout,
125 | "\033[%iG %.2i:%.2i:%.2i:%.6li %15s : %d%s ",
126 | file_col,
127 | my_tm->tm_hour,
128 | my_tm->tm_min,
129 | my_tm->tm_sec,
130 | ts.tv_nsec / 1000,
131 | file,
132 | line,
133 | COLOR_RESET);
134 | }
135 | else
136 | {
137 | fprintf(
138 | stdout,
139 | "\033[%iG %.2i:%.2i:%.2i:%.6li ( %s:%d: )",
140 | file_col,
141 | my_tm->tm_hour,
142 | my_tm->tm_min,
143 | my_tm->tm_sec,
144 | ts.tv_nsec / 1000,
145 | file,
146 | line);
147 | }
148 |
149 | fprintf(stdout, "\n");
150 | }
151 |
152 | void mt_log_set_level(const mt_log_importance importance)
153 | {
154 | min_importance_to_log = importance;
155 | }
156 |
157 | void mt_log_use_colors(const bool colors)
158 | {
159 | use_colors = colors;
160 | }
161 |
162 | void mt_log_set_file_column(int column)
163 | {
164 | file_col = column;
165 | }
166 |
167 | void mt_log_inc_verbosity(void)
168 | {
169 | if (min_importance_to_log != MT_LOG_DEBUG)
170 | {
171 | min_importance_to_log -= 1;
172 | mt_log_debug("Set log level to %s", verbosity_names[min_importance_to_log]);
173 | }
174 | }
175 |
176 | int mt_log_get_level()
177 | {
178 | return min_importance_to_log;
179 | }
180 |
181 | #endif
182 |
--------------------------------------------------------------------------------
/src/mt_core/mt_memory.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_memory_h
2 | #define mt_memory_h
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #define CAL(X, Y, Z) mt_memory_calloc(X, Y, Z);
12 | #define RET(X) mt_memory_retain(X)
13 | #define REL(X) mt_memory_release(X)
14 | #define HEAP(X) mt_memory_stack_to_heap(sizeof(X), NULL, NULL, (char*) &X)
15 |
16 | void* mt_memory_alloc(size_t size, void (*destructor)(void*), void (*descriptor)(void*, int));
17 | void* mt_memory_calloc(size_t size, void (*destructor)(void*), void (*descriptor)(void*, int));
18 | void* mt_memory_realloc(void* pointer, size_t size);
19 | void* mt_memory_retain(void* pointer);
20 | char mt_memory_release(void* pointer);
21 | size_t mt_memory_retaincount(void* pointer);
22 | void* mt_memory_stack_to_heap(size_t size, void (*destructor)(void*), void (*descriptor)(void*, int), char* data);
23 | void mt_memory_describe(void* pointer, int level);
24 |
25 | #endif
26 |
27 | #if __INCLUDE_LEVEL__ == 0
28 |
29 | struct mt_memory_head
30 | {
31 | char id[2];
32 | void (*destructor)(void*);
33 | void (*descriptor)(void*, int);
34 | size_t retaincount;
35 | };
36 |
37 | void* mt_memory_alloc(
38 | size_t size, /* size of data to store */
39 | void (*destructor)(void*), /* optional destructor */
40 | void (*descriptor)(void*, int)) /* optional descriptor for describing memory area */
41 | {
42 | char* bytes = malloc(sizeof(struct mt_memory_head) + size);
43 | if (bytes != NULL)
44 | {
45 | struct mt_memory_head* head = (struct mt_memory_head*) bytes;
46 |
47 | head->id[0] = 'm';
48 | head->id[1] = 't';
49 | head->destructor = destructor;
50 | head->descriptor = descriptor;
51 | head->retaincount = 1;
52 |
53 | return bytes + sizeof(struct mt_memory_head);
54 | }
55 | else
56 | return NULL;
57 | }
58 |
59 | void* mt_memory_calloc(
60 | size_t size, /* size of data to store */
61 | void (*destructor)(void*), /* optional destructor */
62 | void (*descriptor)(void*, int)) /* optional descriptor for describing memory area */
63 | {
64 | char* bytes = calloc(1, sizeof(struct mt_memory_head) + size);
65 |
66 | if (bytes != NULL)
67 | {
68 | struct mt_memory_head* head = (struct mt_memory_head*) bytes;
69 |
70 | head->id[0] = 'm';
71 | head->id[1] = 't';
72 | head->destructor = destructor;
73 | head->descriptor = descriptor;
74 | head->retaincount = 1;
75 |
76 | return bytes + sizeof(struct mt_memory_head);
77 | }
78 | else
79 | return NULL;
80 | }
81 |
82 | void* mt_memory_stack_to_heap(
83 | size_t size,
84 | void (*destructor)(void*),
85 | void (*descriptor)(void*, int),
86 | char* data)
87 | {
88 | char* bytes = mt_memory_alloc(size, destructor, descriptor);
89 |
90 | if (bytes != NULL)
91 | {
92 | memcpy(bytes, data, size);
93 | return bytes;
94 | }
95 | else
96 | return NULL;
97 | }
98 |
99 | void* mt_memory_realloc(void* pointer, size_t size)
100 | {
101 | assert(pointer != NULL);
102 |
103 | char* bytes = (char*) pointer;
104 | bytes -= sizeof(struct mt_memory_head);
105 | bytes = realloc(bytes, sizeof(struct mt_memory_head) + size);
106 | if (bytes != NULL)
107 | {
108 | return bytes + sizeof(struct mt_memory_head);
109 | }
110 | else
111 | return NULL;
112 | }
113 |
114 | void* mt_memory_retain(void* pointer)
115 | {
116 | assert(pointer != NULL);
117 |
118 | char* bytes = (char*) pointer;
119 | bytes -= sizeof(struct mt_memory_head);
120 | struct mt_memory_head* head = (struct mt_memory_head*) bytes;
121 |
122 | assert(head->id[0] == 'm');
123 | assert(head->id[1] == 't');
124 |
125 | if (head->retaincount < SIZE_MAX)
126 | {
127 | head->retaincount += 1;
128 | return pointer;
129 | }
130 | else
131 | return NULL;
132 | }
133 |
134 | char mt_memory_release(void* pointer)
135 | {
136 | assert(pointer != NULL);
137 |
138 | char* bytes = (char*) pointer;
139 | bytes -= sizeof(struct mt_memory_head);
140 | struct mt_memory_head* head = (struct mt_memory_head*) bytes;
141 |
142 | assert(head->id[0] == 'm');
143 | assert(head->id[1] == 't');
144 | assert(head->retaincount > 0);
145 |
146 | head->retaincount -= 1;
147 |
148 | if (head->retaincount == 0)
149 | {
150 | if (head->destructor != NULL)
151 | head->destructor(pointer);
152 |
153 | head->id[0] = '\0';
154 | head->id[1] = '\0';
155 |
156 | free(bytes);
157 |
158 | return 1;
159 | }
160 |
161 | return 0;
162 | }
163 |
164 | size_t mt_memory_retaincount(void* pointer)
165 | {
166 | assert(pointer != NULL);
167 |
168 | char* bytes = (char*) pointer;
169 | bytes -= sizeof(struct mt_memory_head);
170 | struct mt_memory_head* head = (struct mt_memory_head*) bytes;
171 |
172 | assert(head->id[0] == 'm');
173 | assert(head->id[1] == 't');
174 |
175 | return head->retaincount;
176 | }
177 |
178 | void mt_memory_describe(void* pointer, int level)
179 | {
180 | assert(pointer != NULL);
181 |
182 | char* bytes = (char*) pointer;
183 | bytes -= sizeof(struct mt_memory_head);
184 | struct mt_memory_head* head = (struct mt_memory_head*) bytes;
185 |
186 | assert(head->id[0] == 'm');
187 | assert(head->id[1] == 't');
188 |
189 | if (head->descriptor != NULL)
190 | {
191 | head->descriptor(pointer, ++level);
192 | }
193 | else
194 | {
195 | printf("no descriptor");
196 | }
197 | }
198 |
199 | #endif
200 |
--------------------------------------------------------------------------------
/src/mt_core/mt_number.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_number_h
2 | #define mt_number_h
3 |
4 | #include
5 |
6 | typedef union
7 | {
8 | float floatv;
9 | int intv;
10 | uint32_t uint32v;
11 | } mt_number_t;
12 |
13 | mt_number_t* mt_number_new_float(float val);
14 | mt_number_t* mt_number_new_int(int val);
15 | mt_number_t* mt_number_new_uint32(uint32_t val);
16 |
17 | #endif
18 |
19 | #if __INCLUDE_LEVEL__ == 0
20 |
21 | #include "mt_memory.c"
22 |
23 | void mt_number_describe(void* p, int level)
24 | {
25 | mt_number_t* num = p;
26 | printf("num %f %i %u", num->floatv, num->intv, num->uint32v);
27 | }
28 |
29 | mt_number_t* mt_number_new_float(float val)
30 | {
31 | mt_number_t* res = CAL(sizeof(mt_number_t), NULL, mt_number_describe);
32 | res->floatv = val;
33 | return res;
34 | }
35 |
36 | mt_number_t* mt_number_new_int(int val)
37 | {
38 | mt_number_t* res = CAL(sizeof(mt_number_t), NULL, mt_number_describe);
39 | res->intv = val;
40 | return res;
41 | }
42 |
43 | mt_number_t* mt_number_new_uint32(uint32_t val)
44 | {
45 | mt_number_t* res = CAL(sizeof(mt_number_t), NULL, mt_number_describe);
46 | res->uint32v = val;
47 | return res;
48 | }
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/src/mt_core/mt_path.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_path_h
2 | #define mt_path_h
3 |
4 | #include "mt_string.c"
5 |
6 | char* mt_path_new_append(char* root, char* component);
7 | char* mt_path_new_remove_last_component(char* path);
8 | char* mt_path_new_extension(char* path);
9 | char* mt_path_new_filename(char* path);
10 | char* mt_path_new_normalize(char* path);
11 |
12 | #endif
13 |
14 | #if __INCLUDE_LEVEL__ == 0
15 |
16 | #include
17 | #include
18 | #include
19 | #ifdef __linux__
20 | #include
21 | #endif
22 |
23 | #include "mt_log.c"
24 | #include "mt_memory.c"
25 |
26 | char* mt_path_new_append(char* root, char* component)
27 | {
28 | if (root[strlen(root) - 1] == '/')
29 | return mt_string_new_format(PATH_MAX + NAME_MAX, "%s%s", root, component);
30 | else
31 | return mt_string_new_format(PATH_MAX + NAME_MAX, "%s/%s", root, component);
32 | }
33 |
34 | char* mt_path_new_remove_last_component(char* path)
35 | {
36 | /* TODO use POSIX dirname */
37 | int index;
38 | for (index = strlen(path) - 2; index > 0; index--)
39 | {
40 | if (path[index] == '/')
41 | {
42 | index++;
43 | break;
44 | }
45 | }
46 |
47 | if (index > -1)
48 | {
49 | char* str = CAL(index + 1, NULL, mt_string_describe);
50 | memcpy(str, path, index);
51 | return str;
52 | }
53 | else
54 | return mt_string_new_cstring("/");
55 | }
56 |
57 | char* mt_path_new_extension(char* path)
58 | {
59 | char* ext = strrchr(path, '.');
60 | char* res = NULL;
61 | if (ext)
62 | res = mt_string_new_cstring(ext + 1);
63 |
64 | /* int index; */
65 | /* for (index = strlen(path) - 1; index > -1; --index) */
66 | /* { */
67 | /* if (path[index] == '.') */
68 | /* { */
69 | /* index++; */
70 | /* break; */
71 | /* } */
72 | /* } */
73 |
74 | /* int len = strlen(path) - index; */
75 | /* char* ext = CAL(len + 1, NULL, mt_string_describe); */
76 | /* memcpy(ext, path + index, len); */
77 | return res;
78 | }
79 |
80 | char* mt_path_new_filename(char* path)
81 | {
82 | /* TODO use POSIX basename */
83 |
84 | int dotindex;
85 | for (dotindex = strlen(path) - 1; dotindex > -1; --dotindex)
86 | {
87 | if (path[dotindex] == '.')
88 | break;
89 | }
90 |
91 | if (dotindex == -1)
92 | dotindex = strlen(path) - 1;
93 |
94 | int slashindex;
95 | for (slashindex = strlen(path) - 1; slashindex > -1; --slashindex)
96 | {
97 | if (path[slashindex] == '/')
98 | {
99 | slashindex++;
100 | break;
101 | }
102 | }
103 | if (slashindex == -1)
104 | slashindex = 0;
105 | int len = dotindex - slashindex;
106 | char* title = CAL(len + 1, NULL, mt_string_describe);
107 | memcpy(title, path + slashindex, len);
108 | return title;
109 | }
110 |
111 | char* mt_path_new_normalize(char* path)
112 | {
113 | char* extpath = mt_string_new_cstring("");
114 | char* newpath = CAL(PATH_MAX, NULL, NULL);
115 |
116 | if (path[0] == '~')
117 | {
118 | /* replace tilde with home dir */
119 | extpath = mt_string_append(extpath, getenv("HOME"));
120 | extpath = mt_string_append_sub(extpath, path, 1, strlen(path) - 1);
121 | }
122 | else
123 | extpath = mt_string_append(extpath, path);
124 |
125 | realpath(extpath, newpath);
126 |
127 | REL(extpath);
128 |
129 | /* char cwd[PATH_MAX] = {"~"}; */
130 | /* getcwd(cwd, sizeof(cwd)); */
131 |
132 | /* char* newpath = NULL; */
133 |
134 | /* if (path[0] == '~') */
135 | /* { */
136 | /* /\* replace tilde with home dir *\/ */
137 | /* newpath = mt_string_new_cstring(getenv("HOME")); */
138 | /* newpath = mt_string_append_sub(newpath, path, 1, strlen(path) - 1); */
139 | /* } */
140 | /* else if (path[0] == '\0') */
141 | /* { */
142 | /* /\* empty path to root path *\/ */
143 | /* newpath = mt_string_new_cstring("/"); */
144 | /* } */
145 | /* else if (path[0] != '/') */
146 | /* { */
147 | /* /\* insert working directory in case of relative path *\/ */
148 | /* newpath = mt_string_new_format(PATH_MAX, "%s/%s", cwd, path); */
149 | /* } */
150 | /* else */
151 | /* { */
152 | /* newpath = mt_string_new_cstring(path); */
153 | /* } */
154 |
155 | /* /\* remove last component in case of double dot *\/ */
156 |
157 | /* size_t len = strlen(newpath); */
158 | /* if (len > 3 && newpath[len - 1] == '.' && newpath[len - 2] == '.') */
159 | /* { */
160 | /* for (size_t index = len - 3; index-- > 0;) */
161 | /* { */
162 | /* if (newpath[index] == '/') */
163 | /* { */
164 | /* newpath[index] = '\0'; */
165 | /* break; */
166 | /* } */
167 | /* } */
168 | /* } */
169 |
170 | return newpath;
171 | }
172 |
173 | #endif
174 |
--------------------------------------------------------------------------------
/src/mt_core/mt_string.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_string_h
2 | #define mt_string_h
3 |
4 | #include "mt_vector.c"
5 | #include
6 | #include
7 | #include
8 |
9 | #define STRNC(x) mt_string_new_cstring(x)
10 | #define STRNF(x, ...) mt_string_new_format(x, __VA_ARGS__)
11 |
12 | char* mt_string_new_format(int size, char* format, ...);
13 | char* mt_string_new_cstring(char* string);
14 | char* mt_string_new_substring(char* string, size_t from, size_t len);
15 | char* mt_string_reset(char* str);
16 |
17 | char* mt_string_append(char* str, char* add);
18 | char* mt_string_append_cp(char* str, uint32_t cp);
19 | char* mt_string_append_sub(char* str, char* add, size_t from, size_t len);
20 |
21 | char* mt_string_delete_utf_codepoints(char* str, size_t from, size_t len);
22 | mt_vector_t* mt_string_tokenize(char* str, char* del);
23 | void mt_string_describe(void* p, int level);
24 | void mt_string_describe_utf(char* str);
25 |
26 | #endif
27 |
28 | #if __INCLUDE_LEVEL__ == 0
29 |
30 | #include "mt_memory.c"
31 | #include "utf8.h"
32 | #include
33 | #include
34 |
35 | void mt_string_del(void* p)
36 | {
37 | /* printf("DEL %s\n", (char*) p); */
38 | }
39 |
40 | char* mt_string_new_format(int size, char* format, ...)
41 | {
42 | char* result = CAL(sizeof(char) * size, mt_string_del, mt_string_describe);
43 | va_list args;
44 |
45 | va_start(args, format);
46 | vsnprintf(result, size, format, args);
47 | va_end(args);
48 |
49 | return result;
50 | }
51 |
52 | char* mt_string_new_cstring(char* string)
53 | {
54 | char* result = NULL;
55 | if (string != NULL)
56 | {
57 | result = CAL((strlen(string) + 1) * sizeof(char), mt_string_del, mt_string_describe);
58 | memcpy(result, string, strlen(string));
59 | }
60 | return result;
61 | }
62 |
63 | /* TODO calculate UTF8 length */
64 |
65 | char* mt_string_new_substring(char* string, size_t from, size_t len)
66 | {
67 | char* result = NULL;
68 | if (string != NULL && len > from)
69 | {
70 | result = CAL((strlen(string) + 1) * sizeof(char), mt_string_del, mt_string_describe);
71 | memcpy(result, string + from, len);
72 | result[len] = '\0';
73 | }
74 | return result;
75 | }
76 |
77 | char* mt_string_reset(char* str)
78 | {
79 | str[0] = '\0';
80 | return str;
81 | }
82 |
83 | char* mt_string_append(char* str, char* add)
84 | {
85 | size_t needed = strlen(str) + strlen(add) + 1;
86 |
87 | if (strlen(str) < needed)
88 | str = mt_memory_realloc(str, needed);
89 |
90 | str = utf8cat(str, add);
91 |
92 | return str;
93 | }
94 |
95 | char* mt_string_append_cp(char* str, uint32_t cp)
96 | {
97 | size_t size = utf8size(str);
98 | size_t cpsize = utf8codepointsize(cp);
99 | size_t needed = strlen(str) + size + 1;
100 |
101 | if (strlen(str) < needed)
102 | str = mt_memory_realloc(str, needed);
103 |
104 | char* end = str + size - 1;
105 |
106 | end = utf8catcodepoint(end, cp, cpsize);
107 | end[0] = '\0';
108 |
109 | return str;
110 | }
111 |
112 | char* mt_string_append_sub(char* str, char* add, size_t from, size_t len)
113 | {
114 | size_t needed = strlen(str) + len + 1;
115 | int oldsize = strlen(str);
116 |
117 | if (strlen(str) < needed)
118 | str = mt_memory_realloc(str, needed);
119 | memcpy(str + oldsize, add + from, len);
120 | str[needed - 1] = '\0';
121 |
122 | return str;
123 | }
124 |
125 | char* mt_string_delete_utf_codepoints(char* str, size_t from, size_t len)
126 | {
127 | char* res = STRNC("");
128 |
129 | char* curr = str;
130 | utf8_int32_t cp;
131 |
132 | for (size_t index = 0; index < utf8len(str); index++)
133 | {
134 | curr = utf8codepoint(curr, &cp);
135 |
136 | if (index < from || index > from + len)
137 | res = mt_string_append_cp(res, cp);
138 | }
139 |
140 | strcpy(str, res);
141 | REL(res);
142 |
143 | return str;
144 | }
145 |
146 | mt_vector_t* mt_string_tokenize(char* str, char* del)
147 | {
148 | char* token;
149 | char* copy = mt_string_new_cstring(str);
150 | mt_vector_t* result = VNEW();
151 |
152 | token = strtok(copy, del);
153 |
154 | while (token != NULL)
155 | {
156 | char* txt = CAL(strlen(token) + 1, NULL, mt_string_describe);
157 | memcpy(txt, token, strlen(token));
158 |
159 | VADDR(result, txt);
160 |
161 | token = strtok(NULL, del);
162 | }
163 |
164 | REL(copy);
165 |
166 | return result;
167 | }
168 |
169 | void mt_string_describe(void* p, int level)
170 | {
171 | printf("STR: %s", (char*) p);
172 | }
173 |
174 | void mt_string_describe_utf(char* str)
175 | {
176 | char* part = str;
177 | utf8_int32_t cp;
178 | for (size_t i = 0; i < utf8len(str); i++)
179 | {
180 | part = utf8codepoint(part, &cp);
181 | printf("%.4i \t| ", cp);
182 | }
183 | printf("\n");
184 | part = str;
185 | for (size_t i = 0; i < utf8len(str); i++)
186 | {
187 | part = utf8codepoint(part, &cp);
188 | printf("%c \t| ", cp);
189 | }
190 | part = str;
191 | printf("\n");
192 | for (size_t i = 0; i < utf8len(str); i++)
193 | {
194 | part = utf8codepoint(part, &cp);
195 | printf("%zu \t| ", utf8codepointsize(cp));
196 | }
197 | printf("\n");
198 | }
199 |
200 | #endif
201 |
--------------------------------------------------------------------------------
/src/mt_core/mt_time.c:
--------------------------------------------------------------------------------
1 | #ifndef _mt_time_h
2 | #define _mt_time_h
3 |
4 | void mt_time(char* id);
5 |
6 | #endif
7 |
8 | #if __INCLUDE_LEVEL__ == 0
9 |
10 | #include "mt_log.c"
11 | #include
12 | #include
13 |
14 | struct timeval mt_time_stamp;
15 |
16 | void mt_time(char* id)
17 | {
18 | if (id)
19 | {
20 | struct timeval ts;
21 | gettimeofday(&ts, NULL);
22 | mt_log_debug("%s time is %lu us", id, (ts.tv_sec - mt_time_stamp.tv_sec) * 1000000 + ts.tv_usec - mt_time_stamp.tv_usec);
23 | mt_time_stamp = ts;
24 | }
25 | else
26 | {
27 | gettimeofday(&mt_time_stamp, NULL);
28 | }
29 | }
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/src/mt_core/mt_wrapper.c:
--------------------------------------------------------------------------------
1 | /* wraps a non-mtmemory managed pointer */
2 |
3 | #ifndef mt_wrapper_h
4 | #define mt_wrapper_h
5 |
6 | #include
7 |
8 | typedef struct
9 | {
10 | void* data;
11 | } mt_wrapper_t;
12 |
13 | mt_wrapper_t* mt_wrapper_new(void* pointer);
14 |
15 | #endif
16 |
17 | #if __INCLUDE_LEVEL__ == 0
18 |
19 | #include "mt_memory.c"
20 |
21 | mt_wrapper_t* mt_wrapper_new(void* pointer)
22 | {
23 | mt_wrapper_t* res = CAL(sizeof(mt_wrapper_t), NULL, NULL);
24 | res->data = pointer;
25 | return res;
26 | }
27 |
28 | #endif
29 |
--------------------------------------------------------------------------------
/src/mt_core_ext/ku_bitmap_ext.c:
--------------------------------------------------------------------------------
1 | #ifndef bm_util_h
2 | #define bm_util_h
3 |
4 | #include "ku_bitmap.c"
5 | #include
6 |
7 | ku_bitmap_t* bm_new_flip_y(ku_bitmap_t* bm);
8 | void bm_write(ku_bitmap_t* bm, char* path);
9 |
10 | #endif
11 |
12 | #if __INCLUDE_LEVEL__ == 0
13 |
14 | ku_bitmap_t* bm_new_flip_y(ku_bitmap_t* bm)
15 | {
16 | ku_bitmap_t* tmp = ku_bitmap_new(bm->w, bm->h);
17 | for (int y = 0; y < bm->h; y++)
18 | {
19 | int src_y = bm->h - y - 1;
20 | memcpy(tmp->data + y * bm->w * 4, bm->data + src_y * bm->w * 4, bm->w * 4);
21 | }
22 | return tmp;
23 | }
24 |
25 | void bm_write(ku_bitmap_t* bm, char* path)
26 | {
27 | int w = bm->w;
28 | int h = bm->h;
29 |
30 | FILE* f;
31 | unsigned char* img = NULL;
32 | int filesize = 54 + 3 * w * h; // w is your image width, h is image height, both int
33 |
34 | img = (unsigned char*) malloc(3 * w * h);
35 | memset(img, 0, 3 * w * h);
36 |
37 | for (int i = 0; i < w; i++)
38 | {
39 | for (int j = 0; j < h; j++)
40 | {
41 | int index = j * w * 4 + i * 4;
42 |
43 | int x = i;
44 | int y = j;
45 |
46 | int r = bm->data[index];
47 | int g = bm->data[index + 1];
48 | int b = bm->data[index + 2];
49 |
50 | if (r > 255) r = 255;
51 | if (g > 255) g = 255;
52 | if (b > 255) b = 255;
53 |
54 | img[(x + y * w) * 3 + 2] = (unsigned char) (r);
55 | img[(x + y * w) * 3 + 1] = (unsigned char) (g);
56 | img[(x + y * w) * 3 + 0] = (unsigned char) (b);
57 | }
58 | }
59 |
60 | unsigned char bmpfileheader[14] = {'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0};
61 | unsigned char bmpinfoheader[40] = {40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0};
62 | unsigned char bmppad[3] = {0, 0, 0};
63 |
64 | bmpfileheader[2] = (unsigned char) (filesize);
65 | bmpfileheader[3] = (unsigned char) (filesize >> 8);
66 | bmpfileheader[4] = (unsigned char) (filesize >> 16);
67 | bmpfileheader[5] = (unsigned char) (filesize >> 24);
68 |
69 | bmpinfoheader[4] = (unsigned char) (w);
70 | bmpinfoheader[5] = (unsigned char) (w >> 8);
71 | bmpinfoheader[6] = (unsigned char) (w >> 16);
72 | bmpinfoheader[7] = (unsigned char) (w >> 24);
73 | bmpinfoheader[8] = (unsigned char) (h);
74 | bmpinfoheader[9] = (unsigned char) (h >> 8);
75 | bmpinfoheader[10] = (unsigned char) (h >> 16);
76 | bmpinfoheader[11] = (unsigned char) (h >> 24);
77 |
78 | f = fopen(path, "wb");
79 | fwrite(bmpfileheader, 1, 14, f);
80 | fwrite(bmpinfoheader, 1, 40, f);
81 | for (int i = 0; i < h; i++)
82 | {
83 | fwrite(img + (w * (h - i - 1) * 3), 3, w, f);
84 | fwrite(bmppad, 1, (4 - (w * 3) % 4) % 4, f);
85 | }
86 |
87 | free(img);
88 | fclose(f);
89 | }
90 |
91 | #endif
92 |
--------------------------------------------------------------------------------
/src/mt_core_ext/mt_map_ext.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_maputil_h
2 | #define mt_maputil_h
3 |
4 | #include "mt_map.c"
5 | #include "mt_string.c"
6 |
7 | typedef struct _mpair_t
8 | {
9 | char* key;
10 | char* value;
11 | } mpair_t;
12 |
13 | mt_map_t* mapu_pair(mpair_t pair);
14 |
15 | #endif
16 |
17 | #if __INCLUDE_LEVEL__ == 0
18 |
19 | mt_map_t* mapu_pair(mpair_t pair)
20 | {
21 | mt_map_t* result = MNEW();
22 | char* str = mt_string_new_cstring(pair.value); // REL 0
23 | MPUT(result, pair.key, str);
24 | REL(str); // REL 0
25 | REL(pair.value);
26 | return result;
27 | }
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/src/mt_core_ext/mt_string_ext.c:
--------------------------------------------------------------------------------
1 | #ifndef cstr_util_h
2 | #define cstr_util_h
3 |
4 | #include "mt_string.c"
5 | #include "mt_vector.c"
6 | #include
7 | #include
8 |
9 | char* mt_string_new_file(char* path);
10 | uint32_t mt_string_color_from_cstring(char* string);
11 | char* mt_string_new_readablec(uint32_t length);
12 | char* mt_string_new_alphanumeric(uint32_t length);
13 | void mt_string_tolower(char* str);
14 | mt_vector_t* mt_string_split(char* str, char* del);
15 | char* mt_string_unescape(char* str);
16 |
17 | #endif
18 |
19 | #if __INCLUDE_LEVEL__ == 0
20 |
21 | #include "mt_memory.c"
22 |
23 | static char hexa[] =
24 | {
25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0..9
26 | 0,
27 | 0,
28 | 0,
29 | 0,
30 | 0,
31 | 0,
32 | 0,
33 | 0,
34 | 0,
35 | 0, // 10..19
36 | 0,
37 | 0,
38 | 0,
39 | 0,
40 | 0,
41 | 0,
42 | 0,
43 | 0,
44 | 0,
45 | 0, // 20..29
46 | 0,
47 | 0,
48 | 0,
49 | 0,
50 | 0,
51 | 0,
52 | 0,
53 | 0,
54 | 0,
55 | 0, // 30..39
56 | 0,
57 | 0,
58 | 0,
59 | 0,
60 | 0,
61 | 0,
62 | 0,
63 | 0,
64 | 0,
65 | 1, // 40..49
66 | 2,
67 | 3,
68 | 4,
69 | 5,
70 | 6,
71 | 7,
72 | 8,
73 | 9,
74 | 0,
75 | 0, // 50..59
76 | 0,
77 | 0,
78 | 0,
79 | 0,
80 | 0,
81 | 10,
82 | 11,
83 | 12,
84 | 13,
85 | 14, // 60..69
86 | 15,
87 | 0,
88 | 0,
89 | 0,
90 | 0,
91 | 0,
92 | 0,
93 | 0,
94 | 0,
95 | 0, // 70..79
96 | 0,
97 | 0,
98 | 0,
99 | 0,
100 | 0,
101 | 0,
102 | 0,
103 | 0,
104 | 0,
105 | 0, // 80..89
106 | 0,
107 | 0,
108 | 0,
109 | 0,
110 | 0,
111 | 0,
112 | 0,
113 | 10,
114 | 11,
115 | 12, // 90..99
116 | 13,
117 | 14,
118 | 15,
119 | 0,
120 | 0,
121 | 0,
122 | 0,
123 | 0,
124 | 0,
125 | 0 // 100..109
126 | };
127 |
128 | /* returns uint value based on digits */
129 |
130 | uint32_t mt_string_color_from_cstring(char* string)
131 | {
132 | uint32_t result = 0;
133 | while (*string != 0)
134 | result = result << 4 | hexa[(int) *string++];
135 | return result;
136 | }
137 |
138 | /* reads up text file */
139 |
140 | char* mt_string_new_file(char* path)
141 | {
142 | char* buffer = NULL;
143 | int string_size, read_size;
144 | FILE* handler = fopen(path, "r");
145 |
146 | if (handler)
147 | {
148 | // Seek the last byte of the file
149 | fseek(handler, 0, SEEK_END);
150 | // Offset from the first to the last byte, or in other words, filesize
151 | string_size = ftell(handler);
152 | // go back to the start of the file
153 | rewind(handler);
154 |
155 | // Allocate a string that can hold it all
156 | buffer = (char*) CAL(sizeof(char) * (string_size + 1), NULL, mt_string_describe);
157 |
158 | // Read it all in one operation
159 | read_size = fread(buffer, sizeof(char), string_size, handler);
160 |
161 | // fread doesn't set it so put a \0 in the last position
162 | // and buffer is now officially a string
163 | buffer[string_size] = '\0';
164 |
165 | if (string_size != read_size)
166 | {
167 | // Something went wrong, throw away the memory and set
168 | // the buffer to NULL
169 | free(buffer);
170 | buffer = NULL;
171 | }
172 |
173 | // Always remember to close the file.
174 | fclose(handler);
175 | }
176 |
177 | return buffer;
178 | }
179 |
180 | /* generates readable string */
181 |
182 | char* vowels = "aeiou";
183 | char* consonants = "bcdefghijklmnpqrstvwxyz";
184 |
185 | char* mt_string_new_readablec(uint32_t length)
186 | {
187 | char* result = CAL(sizeof(char) * (length + 1), NULL, mt_string_describe);
188 | for (size_t index = 0; index < length; index += 2)
189 | {
190 | result[index] = consonants[rand() % strlen(consonants)];
191 | if (index + 1 < length)
192 | result[index + 1] = vowels[rand() % strlen(vowels)];
193 | }
194 | return result;
195 | }
196 |
197 | void mt_string_tolower(char* str)
198 | {
199 | for (size_t index = 0; index < strlen(str); index++)
200 | {
201 | str[index] = tolower(str[index]);
202 | }
203 | }
204 |
205 | /* generates alphanumeric string */
206 |
207 | char* mt_string_alphanumeric =
208 | "0123456789"
209 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
210 | "abcdefghijklmnopqrstuvwxyz";
211 |
212 | char* mt_string_new_alphanumeric(uint32_t length)
213 | {
214 | char* result = CAL(sizeof(char) * (length + 1), NULL, mt_string_describe);
215 | for (size_t index = 0; index < length; index++)
216 | {
217 | result[index] = mt_string_alphanumeric[rand() % strlen(mt_string_alphanumeric)];
218 | }
219 | return result;
220 | }
221 |
222 | mt_vector_t* mt_string_split(char* str, char* del)
223 | {
224 | char* token;
225 | mt_vector_t* result = VNEW();
226 |
227 | char* copy = mt_string_new_cstring(str);
228 | token = strtok(copy, del);
229 |
230 | while (token != NULL)
231 | {
232 | char* txt = CAL(strlen(token) + 1, NULL, mt_string_describe);
233 | memcpy(txt, token, strlen(token));
234 |
235 | VADDR(result, txt);
236 |
237 | token = strtok(NULL, del);
238 | }
239 |
240 | REL(copy);
241 |
242 | return result;
243 | }
244 |
245 | char* mt_string_unescape(char* str)
246 | {
247 | size_t length = strlen(str);
248 | char* result = CAL((length + 1) * sizeof(char), NULL, mt_string_describe);
249 | int ni = 0;
250 | for (size_t index = 0; index < length; index++)
251 | {
252 | if (str[index] == '\\')
253 | {
254 | if (index < length - 1)
255 | {
256 | char n = str[index + 1];
257 | if (n == '\\' || n == '"' || n == '\'' || n == '/' || n == '?')
258 | {
259 | result[ni++] = n;
260 | }
261 | index += 1;
262 | }
263 | }
264 | else
265 | {
266 | result[ni++] = str[index];
267 | }
268 | }
269 | return result;
270 | }
271 |
272 | #endif
273 |
--------------------------------------------------------------------------------
/src/mt_core_test/mt_channel_test.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_channel_test_h
2 | #define mt_channel_test_h
3 |
4 | void mt_channel_test_main();
5 |
6 | #endif
7 |
8 | #if __INCLUDE_LEVEL__ == 0
9 |
10 | #include "mt_channel.c"
11 | #include "mt_log.c"
12 | #include "mt_map.c"
13 |
14 | #define kChTestThreads 20
15 | #define kChTestMax 60000
16 |
17 | static int success = 1;
18 |
19 | void* send_test(void* chp)
20 | {
21 | mt_channel_t* ch = chp;
22 | uint32_t counter = 0;
23 | while (1)
24 | {
25 | if (success == 0)
26 | break;
27 |
28 | uint32_t* number = CAL(sizeof(uint32_t), NULL, NULL);
29 | *number = counter;
30 | char sent = mt_channel_send(ch, number);
31 |
32 | if (sent == 0)
33 | {
34 | REL(number);
35 | }
36 | else
37 | {
38 | counter += 1;
39 | if (counter == kChTestMax)
40 | break;
41 | }
42 |
43 | // struct timespec time;
44 | // time.tv_sec = 0;
45 | // time.tv_nsec = rand() % 100000;
46 | // nanosleep(&time , (struct timespec *)NULL);
47 | }
48 |
49 | return NULL;
50 | }
51 |
52 | void* recv_test(void* chp)
53 | {
54 | mt_channel_t* ch = chp;
55 | uint32_t last = 0;
56 | while (1)
57 | {
58 | if (success == 0)
59 | break;
60 |
61 | uint32_t* number = mt_channel_recv(ch);
62 | if (number != NULL)
63 | {
64 | if (*number != last)
65 | {
66 | success = 0;
67 | /* printf("index error!!! %u %u %i\n", *number, last, success); */
68 | break;
69 | }
70 |
71 | REL(number);
72 | last += 1;
73 |
74 | if (last == kChTestMax)
75 | break;
76 |
77 | // struct timespec time;
78 | // time.tv_sec = 0;
79 | // time.tv_nsec = rand() % 100000;
80 | // nanosleep(&time , (struct timespec *)NULL);
81 | }
82 | }
83 |
84 | return NULL;
85 | }
86 |
87 | mt_channel_t** testarray;
88 |
89 | void mt_channel_test_main()
90 | {
91 | mt_log_debug("testing mt_channel");
92 |
93 | testarray = CAL(sizeof(mt_channel_t) * kChTestThreads, NULL, NULL);
94 |
95 | pthread_t* threads = CAL(sizeof(pthread_t) * kChTestThreads * 2, NULL, NULL);
96 |
97 | uint32_t threadidx = 0;
98 |
99 | for (int index = 0; index < kChTestThreads; index++)
100 | {
101 | testarray[index] = mt_channel_new(100);
102 | pthread_create(&threads[threadidx++], NULL, send_test, testarray[index]);
103 | pthread_create(&threads[threadidx++], NULL, recv_test, testarray[index]);
104 | }
105 |
106 | for (uint32_t index = 0; index < threadidx; index++)
107 | {
108 | pthread_join(threads[index], NULL);
109 | }
110 |
111 | REL(threads);
112 |
113 | assert(success == 1);
114 | }
115 |
116 | #endif
117 |
--------------------------------------------------------------------------------
/src/mt_core_test/mt_core_test.c:
--------------------------------------------------------------------------------
1 | #include "mt_channel_test.c"
2 | #include "mt_log.c"
3 | #include "mt_map_test.c"
4 | #include "mt_memory_test.c"
5 | #include "mt_path_test.c"
6 | #include "mt_string_test.c"
7 | #include "mt_vector_test.c"
8 |
9 | int main(int argc, char* argv[])
10 | {
11 | mt_log_set_level(MT_LOG_DEBUG);
12 |
13 | mt_memory_test_main();
14 | mt_vector_test_main();
15 | mt_map_test_main();
16 | mt_string_test_main();
17 | mt_channel_test_main();
18 | mt_path_test_main();
19 |
20 | return 0;
21 | }
22 |
--------------------------------------------------------------------------------
/src/mt_core_test/mt_map_test.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_map_test_h
2 | #define mt_map_test_h
3 |
4 | void mt_map_test_main();
5 |
6 | #endif
7 |
8 | #if __INCLUDE_LEVEL__ == 0
9 |
10 | #include "mt_log.c"
11 | #include "mt_map.c"
12 |
13 | void mt_map_test_main()
14 | {
15 | char* text1 = "Test text 1";
16 | char* text2 = "Test text 2";
17 |
18 | char* ttext1 = mt_memory_stack_to_heap(strlen(text1) + 1, NULL, NULL, (char*) text1);
19 | char* ttext2 = mt_memory_stack_to_heap(strlen(text2) + 1, NULL, NULL, (char*) text2);
20 |
21 | /* checking if map is allocated correctly */
22 |
23 | mt_log_debug("testing mt_map_new");
24 |
25 | mt_map_t* map1 = mt_map_new();
26 |
27 | assert(map1 != NULL);
28 | assert(map1->count == 0);
29 |
30 | /* checking if put works correctly */
31 |
32 | mt_log_debug("testing mt_map_put");
33 |
34 | mt_map_put(map1, "text1", ttext1);
35 |
36 | char* ctext1 = mt_map_get(map1, "text1");
37 |
38 | assert(ttext1 == ctext1);
39 |
40 | /* checking if put release working correctly by checking retain counter */
41 |
42 | mt_log_debug("testing mt_map_put_rel");
43 |
44 | mt_map_put_rel(map1, "text2", ttext2);
45 |
46 | char* ctext2 = mt_map_get(map1, "text2");
47 |
48 | assert(ttext2 == ctext2);
49 | assert(mt_memory_retaincount(ttext2) == 1);
50 |
51 | /* checking if map_keys working correctly */
52 |
53 | mt_log_debug("testing mt_map_keys");
54 |
55 | mt_vector_t* keys = mt_vector_new();
56 |
57 | mt_map_keys(map1, keys);
58 |
59 | assert(keys->length == 2);
60 |
61 | for (size_t index = 0; index < keys->length; index++)
62 | {
63 | char* key = keys->data[index];
64 |
65 | assert(strcmp(key, "text1") == 0 || strcmp(key, "text2") == 0);
66 | }
67 |
68 | REL(keys);
69 |
70 | /* checking if map_values working correctly */
71 |
72 | mt_log_debug("testing mt_map_values");
73 |
74 | mt_vector_t* vals = mt_vector_new();
75 |
76 | mt_map_values(map1, vals);
77 |
78 | assert(vals->length == 2);
79 |
80 | for (size_t index = 0; index < vals->length; index++)
81 | {
82 | char* val = vals->data[index];
83 |
84 | assert(val == ttext1 || val == ttext2);
85 | }
86 |
87 | REL(vals);
88 |
89 | /* checking if map_del working correctly */
90 |
91 | mt_log_debug("testing mt_map_del");
92 |
93 | mt_map_del(map1, "text2");
94 |
95 | assert(map1->count == 1);
96 | assert(mt_map_get(map1, "text2") == NULL);
97 |
98 | /* checking if map_reset working correctly */
99 |
100 | mt_log_debug("testing mt_map_reset");
101 |
102 | mt_map_reset(map1);
103 |
104 | assert(map1->count == 0);
105 |
106 | /* cleanup, run with leak sanitizer on to check for hidden leaks */
107 |
108 | REL(ttext1);
109 | REL(map1);
110 | }
111 |
112 | #endif
113 |
--------------------------------------------------------------------------------
/src/mt_core_test/mt_memory_test.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_memory_test_h
2 | #define mt_memory_test_h
3 |
4 | void mt_memory_test_main();
5 |
6 | #endif
7 |
8 | #if __INCLUDE_LEVEL__ == 0
9 |
10 | #include "mt_log.c"
11 | #include "mt_memory.c"
12 | #include
13 |
14 | void test_alloc()
15 | {
16 | mt_log_debug("testing mt_memory_alloc");
17 |
18 | char* atext = NULL;
19 |
20 | atext = mt_memory_alloc(sizeof(char) * 80, NULL, NULL);
21 |
22 | assert(atext != NULL);
23 | assert(mt_memory_retaincount(atext) == 1);
24 |
25 | mt_memory_release(atext);
26 | }
27 |
28 | void test_calloc()
29 | {
30 | mt_log_debug("testing mt_memory_calloc");
31 |
32 | char* ctext = NULL;
33 |
34 | ctext = mt_memory_calloc(sizeof(char) * 80, NULL, NULL);
35 |
36 | assert(ctext != NULL);
37 | assert(mt_memory_retaincount(ctext) == 1);
38 |
39 | mt_memory_release(ctext);
40 | }
41 |
42 | void test_stack_to_heap()
43 | {
44 | mt_log_debug("testing mt_memory_stack_to_heap");
45 |
46 | char* text = "This is a test string";
47 | char* ttext = mt_memory_stack_to_heap(strlen(text) + 1, NULL, NULL, (char*) text);
48 |
49 | assert(ttext != NULL);
50 | assert(mt_memory_retaincount(ttext) == 1);
51 | assert(strcmp(ttext, text) == 0);
52 |
53 | mt_memory_release(ttext);
54 | }
55 |
56 | void test_realloc()
57 | {
58 | mt_log_debug("testing mt_memory_realloc");
59 |
60 | char* text0 = "This is a test string";
61 | char* text1 = "Another text string";
62 | char* ttext = mt_memory_calloc(strlen(text0) + 1, NULL, NULL);
63 | memcpy(ttext, text0, strlen(text0));
64 |
65 | ttext = mt_memory_realloc(ttext, strlen(text0) + strlen(text1) + 1);
66 | memcpy(ttext + strlen(text0), text1, strlen(text1));
67 |
68 | assert(ttext != NULL);
69 | assert(mt_memory_retaincount(ttext) == 1);
70 | assert(strstr(ttext, text0) != NULL);
71 | assert(strstr(ttext, text1) != NULL);
72 |
73 | mt_memory_release(ttext);
74 | }
75 |
76 | int destruct_count = 1;
77 |
78 | void destruct()
79 | {
80 | destruct_count -= 1;
81 | }
82 |
83 | void test_destructor()
84 | {
85 | mt_log_debug("testing mt_memory descructor");
86 |
87 | char* atext = NULL;
88 |
89 | atext = mt_memory_alloc(sizeof(char) * 80, destruct, NULL);
90 |
91 | assert(atext != NULL);
92 | assert(mt_memory_retaincount(atext) == 1);
93 |
94 | mt_memory_release(atext);
95 |
96 | assert(destruct_count == 0);
97 | }
98 |
99 | int describe_count = 1;
100 |
101 | void describe()
102 | {
103 | describe_count -= 1;
104 | }
105 |
106 | void test_descriptor()
107 | {
108 | mt_log_debug("testing mt_memory descriptor");
109 |
110 | char* atext = NULL;
111 |
112 | atext = mt_memory_alloc(sizeof(char) * 80, NULL, describe);
113 |
114 | assert(atext != NULL);
115 | assert(mt_memory_retaincount(atext) == 1);
116 |
117 | mt_memory_describe(atext, 0);
118 | mt_memory_release(atext);
119 |
120 | assert(describe_count == 0);
121 | }
122 |
123 | /* run test with clang leak sanitizer */
124 |
125 | void mt_memory_test_main()
126 | {
127 | test_alloc();
128 | test_calloc();
129 | test_stack_to_heap();
130 | test_realloc();
131 | test_destructor();
132 | test_descriptor();
133 | }
134 |
135 | #endif
136 |
--------------------------------------------------------------------------------
/src/mt_core_test/mt_path_test.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_path_test_h
2 | #define mt_path_test_h
3 |
4 | void mt_path_test_main();
5 |
6 | #endif
7 |
8 | #if __INCLUDE_LEVEL__ == 0
9 |
10 | #include "mt_log.c"
11 | #include "mt_path.c"
12 | #include
13 | #include
14 |
15 | void mt_path_test_main()
16 | {
17 | /* checking if mt_path_new_format works */
18 |
19 | mt_log_debug("testing mt_path_new_append");
20 |
21 | char* path1 = mt_path_new_append("root", "exec/");
22 |
23 | assert(strcmp(path1, "root/exec/") == 0);
24 |
25 | /* checking if mt_path_new_remove_last_component works */
26 |
27 | mt_log_debug("testing mt_path_new_remove_last_component");
28 |
29 | char* path2 = mt_path_new_remove_last_component("/home/milgra/whatever.ext");
30 |
31 | assert(strcmp(path2, "/home/milgra/") == 0);
32 |
33 | /* checking if mt_path_new_extension works */
34 |
35 | mt_log_debug("testing mt_path_new_extension");
36 |
37 | char* path3 = mt_path_new_extension("/home/milgra/whatever.ext");
38 |
39 | assert(strcmp(path3, "ext") == 0);
40 |
41 | /* checking if mt_path_new_filename works */
42 |
43 | mt_log_debug("testing mt_path_new_filename");
44 |
45 | char* path4 = mt_path_new_filename("/home/milgra/whatever.ext");
46 |
47 | assert(strcmp(path4, "whatever") == 0);
48 |
49 | /* checking if mt_path_new_normalize works */
50 |
51 | mt_log_debug("testing mt_path_new_normalize");
52 |
53 | char* path5 = mt_path_new_normalize("//milcsi/../whatever.ext");
54 |
55 | assert(strcmp(path5, "//whatever.ext"));
56 |
57 | REL(path1);
58 | REL(path2);
59 | REL(path3);
60 | REL(path4);
61 | REL(path5);
62 | }
63 |
64 | #endif
65 |
--------------------------------------------------------------------------------
/src/mt_core_test/mt_string_test.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_string_test_h
2 | #define mt_string_test_h
3 |
4 | void mt_string_test_main();
5 |
6 | #endif
7 |
8 | #if __INCLUDE_LEVEL__ == 0
9 |
10 | #include "mt_log.c"
11 | #include "mt_string.c"
12 |
13 | void mt_string_test_main()
14 | {
15 | /* char* str = "000 Állítólag svájcban"; */
16 |
17 | /* checking if mt_string_new_format works */
18 |
19 | mt_log_debug("testing mt_string_new_format");
20 |
21 | char* str1 = mt_string_new_format(100, "%s-%i-%x", "milcsi", 100, 64);
22 |
23 | assert(strcmp(str1, "milcsi-100-40") == 0);
24 |
25 | /* checking if mt_string_new_cstring works */
26 |
27 | mt_log_debug("testing mt_string_new_cstring");
28 |
29 | char* str2 = mt_string_new_cstring("another cstring");
30 |
31 | assert(strcmp(str2, "another cstring") == 0);
32 |
33 | /* checking if mt_string_new_substring works */
34 |
35 | mt_log_debug("testing mt_string_new_substring");
36 |
37 | char* str3 = mt_string_new_substring("another cstring", 3, 6);
38 |
39 | assert(strcmp(str3, "ther c") == 0);
40 |
41 | /* checking if mt_string_reset works */
42 |
43 | mt_log_debug("testing mt_string_reset");
44 |
45 | str1 = mt_string_reset(str1);
46 |
47 | assert(strlen(str1) == 0);
48 |
49 | /* checking if mt_string_append works */
50 |
51 | mt_log_debug("testing mt_string_append");
52 |
53 | str1 = mt_string_append(str1, "new string");
54 | str1 = mt_string_append(str1, "|old string");
55 |
56 | assert(strcmp(str1, "new string|old string") == 0);
57 |
58 | /* checking if mt_string_append works */
59 |
60 | mt_log_debug("testing mt_string_append_cp");
61 |
62 | str1 = mt_string_append_cp(str1, 588);
63 |
64 | assert(strcmp(str1, "new string|old stringɌ") == 0);
65 |
66 | /* checking if mt_string_append_sub works */
67 |
68 | mt_log_debug("testing mt_string_append_sub");
69 |
70 | str2 = mt_string_append_sub(str2, "WHAT THE", 2, 3);
71 |
72 | assert(strcmp(str2, "another cstringAT ") == 0);
73 |
74 | /* checking if mt_string_delete_utf_codepoints works */
75 |
76 | mt_log_debug("testing mt_string_delete_utf_codepoints");
77 |
78 | str1 = mt_string_delete_utf_codepoints(str1, 4, 18);
79 |
80 | assert(strcmp(str1, "new ") == 0);
81 |
82 | /* checking if mt_string_tokenize works */
83 |
84 | mt_log_debug("testing mt_string_tokenize");
85 |
86 | mt_vector_t* vec = mt_string_tokenize("ONE TWO THREE", " ");
87 |
88 | assert(vec->length == 3);
89 | assert(strcmp(vec->data[0], "ONE") == 0);
90 | assert(strcmp(vec->data[1], "TWO") == 0);
91 | assert(strcmp(vec->data[2], "THREE") == 0);
92 |
93 | REL(vec);
94 | REL(str1);
95 | REL(str2);
96 | REL(str3);
97 | }
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/src/mt_core_test/mt_vector_test.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_vector_test_h
2 | #define mt_vector_test_h
3 |
4 | void mt_vector_test_main();
5 |
6 | #endif
7 |
8 | #if __INCLUDE_LEVEL__ == 0
9 |
10 | #include "mt_log.c"
11 | #include "mt_vector.c"
12 |
13 | void mt_vector_test_main()
14 | {
15 | char* text1 = "Test text 1";
16 | char* text2 = "Test text 2";
17 | char* text3 = "Test text 3";
18 | char* text4 = "Test text 4";
19 |
20 | char* ttext1 = mt_memory_stack_to_heap(strlen(text1) + 1, NULL, NULL, (char*) text1);
21 | char* ttext2 = mt_memory_stack_to_heap(strlen(text2) + 1, NULL, NULL, (char*) text2);
22 | char* ttext3 = mt_memory_stack_to_heap(strlen(text3) + 1, NULL, NULL, (char*) text3);
23 | char* ttext4 = mt_memory_stack_to_heap(strlen(text4) + 1, NULL, NULL, (char*) text4);
24 |
25 | /* checking if vector allocated correctly */
26 |
27 | mt_log_debug("testing mt_vector_new");
28 |
29 | mt_vector_t* vec1 = mt_vector_new();
30 |
31 | assert(vec1 != NULL);
32 | assert(vec1->length == 0);
33 |
34 | /* checking if add works correctly */
35 |
36 | mt_log_debug("testing mt_vector_add");
37 |
38 | mt_vector_add(vec1, ttext1);
39 |
40 | assert(vec1->length == 1);
41 | assert(vec1->data[0] == ttext1);
42 |
43 | /* checking if add release works correctly */
44 |
45 | mt_log_debug("testing mt_vector_add_rel");
46 |
47 | mt_vector_add_rel(vec1, ttext2);
48 |
49 | assert(vec1->length == 2);
50 | assert(vec1->data[1] == ttext2);
51 | assert(mt_memory_retaincount(ttext2) == 1);
52 |
53 | /* checking if insert works correctly */
54 |
55 | mt_log_debug("testing mt_vector_insert");
56 |
57 | mt_vector_ins(vec1, ttext3, 1);
58 |
59 | assert(vec1->length == 3);
60 | assert(vec1->data[1] == ttext3);
61 |
62 | /* checking if insert release works correctly */
63 |
64 | mt_log_debug("testing mt_vector_insert_rel");
65 |
66 | mt_vector_ins_rel(vec1, ttext4, 2);
67 |
68 | assert(vec1->length == 4);
69 | assert(vec1->data[2] == ttext4);
70 | assert(mt_memory_retaincount(ttext4) == 1);
71 |
72 | RET(ttext4);
73 |
74 | /* checking if remove data works correctly */
75 |
76 | mt_log_debug("testing mt_vector_rem");
77 |
78 | mt_vector_rem(vec1, ttext1);
79 |
80 | assert(vec1->length == 3);
81 | assert(vec1->data[0] == ttext3);
82 |
83 | /* checking if remove index works correctly */
84 |
85 | mt_log_debug("testing mt_vector_rem_index");
86 |
87 | mt_vector_rem_index(vec1, 1);
88 |
89 | assert(vec1->length == 2);
90 | assert(vec1->data[1] == ttext2);
91 |
92 | /* checking if remove range works correctly */
93 |
94 | mt_log_debug("testing mt_vector_rem_range");
95 |
96 | mt_vector_rem_range(vec1, 0, 1);
97 |
98 | assert(vec1->length == 0);
99 |
100 | /* checking add in vector */
101 |
102 | mt_vector_t* vec2 = mt_vector_new();
103 | mt_vector_add(vec2, ttext1);
104 | mt_vector_add(vec2, ttext2);
105 | mt_vector_add(vec2, ttext3);
106 | mt_vector_add(vec2, ttext4);
107 |
108 | mt_log_debug("testing mt_vector_add_in_vector");
109 |
110 | mt_vector_add_in_vector(vec1, vec2);
111 |
112 | assert(vec1->length == 4);
113 | assert(vec1->data[3] == ttext4);
114 |
115 | /* checking remove in vector */
116 |
117 | mt_log_debug("testing mt_vector_rem_in_vector");
118 |
119 | mt_vector_rem_in_vector(vec1, vec2);
120 |
121 | assert(vec1->length == 0);
122 |
123 | /* checking head and tail */
124 |
125 | mt_vector_add(vec1, ttext1);
126 | mt_vector_add(vec1, ttext2);
127 | mt_vector_add(vec1, ttext3);
128 | mt_vector_add(vec1, ttext4);
129 |
130 | mt_log_debug("testing mt_vector_head");
131 |
132 | assert(mt_vector_head(vec1) == ttext1);
133 |
134 | mt_log_debug("testing mt_vector_tail");
135 |
136 | assert(mt_vector_tail(vec1) == ttext4);
137 |
138 | /* checking reverse */
139 |
140 | mt_log_debug("testing mt_vector_reverse");
141 |
142 | mt_vector_reverse(vec1);
143 |
144 | assert(vec1->length == 4);
145 | assert(vec1->data[0] == ttext4);
146 | assert(vec1->data[3] == ttext1);
147 |
148 | /* checking sort */
149 |
150 | mt_log_debug("testing mt_vector_sort");
151 |
152 | mt_vector_sort(vec1, (int (*)(void*, void*)) strcmp);
153 |
154 | assert(vec1->length == 4);
155 | assert(vec1->data[0] == ttext1);
156 | assert(vec1->data[3] == ttext4);
157 |
158 | /* checking index of */
159 |
160 | assert(mt_vector_index_of_data(vec1, ttext2) == 1);
161 |
162 | REL(vec1);
163 | REL(vec2);
164 | REL(ttext1);
165 | REL(ttext2);
166 | REL(ttext3);
167 | REL(ttext4);
168 | REL(ttext4);
169 | }
170 |
171 | #endif
172 |
--------------------------------------------------------------------------------
/src/mt_math/mt_vector_2d.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_vector_2d_h
2 | #define mt_vector_2d_h
3 |
4 | #include
5 | #include
6 |
7 | typedef struct _v2_t v2_t;
8 | struct _v2_t
9 | {
10 | float x, y;
11 | };
12 |
13 | v2_t v2_init(float x, float y);
14 | v2_t v2_add(v2_t a, v2_t b);
15 | v2_t v2_sub(v2_t a, v2_t b);
16 | v2_t v2_scale(v2_t vector, float ratio);
17 | v2_t v2_resize(v2_t a, float size);
18 | v2_t v2_rotate(v2_t vector, float newangle);
19 | v2_t v2_rotate_90_left(v2_t vector);
20 | v2_t v2_rotate_90_right(v2_t vector);
21 |
22 | v2_t v2_midpoints(v2_t pointa, v2_t pointb);
23 | float v2_length(v2_t a);
24 | float v2_angle_x(v2_t a);
25 | float v2_circular_angle_between(v2_t a, v2_t b);
26 | char v2_equals(v2_t a, v2_t b);
27 | void v2_describe(v2_t vector);
28 | float v2_longside(v2_t a);
29 |
30 | #endif
31 |
32 | #if __INCLUDE_LEVEL__ == 0
33 |
34 | #ifndef M_PI
35 | #define M_PI 3.14159265358979323846
36 | #endif
37 |
38 | /* creates vector2 */
39 |
40 | v2_t v2_init(float x, float y)
41 | {
42 | v2_t result;
43 |
44 | result.x = x;
45 | result.y = y;
46 |
47 | return result;
48 | }
49 |
50 | /* adds two vectors */
51 |
52 | v2_t v2_add(v2_t a, v2_t b)
53 | {
54 | v2_t result;
55 |
56 | result.x = a.x + b.x;
57 | result.y = a.y + b.y;
58 |
59 | return result;
60 | }
61 |
62 | /* substracts b from a */
63 |
64 | v2_t v2_sub(v2_t a, v2_t b)
65 | {
66 | v2_t result;
67 |
68 | result.x = a.x - b.x;
69 | result.y = a.y - b.y;
70 |
71 | return result;
72 | }
73 |
74 | /* multiplies vector with ratio */
75 |
76 | v2_t v2_scale(v2_t vector, float ratio)
77 | {
78 | v2_t result;
79 |
80 | result.x = vector.x * ratio;
81 | result.y = vector.y * ratio;
82 |
83 | return result;
84 | }
85 |
86 | /* resizes vector */
87 |
88 | v2_t v2_resize(v2_t a, float size)
89 | {
90 | float length = sqrtf(a.x * a.x + a.y * a.y);
91 | float ratio = size / length;
92 | a.x *= ratio;
93 | a.y *= ratio;
94 | return a;
95 | }
96 |
97 | /* rotates vector with given radians */
98 |
99 | v2_t v2_rotate(v2_t vector, float newangle)
100 | {
101 | float angle = v2_angle_x(vector);
102 | float length = v2_length(vector);
103 | angle += newangle;
104 | return v2_init(cos(angle) * length, sin(angle) * length);
105 | }
106 |
107 | /* rotates vector to left with 90 degrees */
108 |
109 | v2_t v2_rotate_90_left(v2_t vector)
110 | {
111 | return v2_init(-vector.y, vector.x);
112 | }
113 |
114 | /* rotates vector to right with 90 degrees */
115 |
116 | v2_t v2_rotate_90_right(v2_t vector)
117 | {
118 | return v2_init(vector.y, -vector.x);
119 | }
120 |
121 | /* returns middle point */
122 |
123 | v2_t v2_midpoints(v2_t pointa, v2_t pointb)
124 | {
125 | v2_t pointc = v2_sub(pointb, pointa);
126 |
127 | pointc = v2_scale(pointc, 0.5);
128 | pointc = v2_add(pointa, pointc);
129 |
130 | return pointc;
131 | }
132 |
133 | /* returns vector length */
134 |
135 | float v2_length(v2_t a)
136 | {
137 | return sqrtf(a.x * a.x + a.y * a.y);
138 | }
139 |
140 | /* returns vector angel on x axis */
141 |
142 | float v2_angle_x(v2_t a)
143 | {
144 | return atan2(a.y, a.x);
145 | }
146 |
147 | /* returns angle between two vector as a circular CCW angle where angle 0 is
148 | * vector a */
149 |
150 | float v2_circular_angle_between(v2_t a, v2_t b)
151 | {
152 | float anglea = v2_angle_x(a);
153 | float angleb = v2_angle_x(b);
154 |
155 | float anglere = angleb - anglea;
156 | if (anglere < 0.0)
157 | anglere += 2 * M_PI;
158 | return anglere;
159 | }
160 |
161 | /* compares two vectors */
162 |
163 | char v2_equals(v2_t a, v2_t b)
164 | {
165 | return a.x == b.x && a.y == b.y;
166 | }
167 |
168 | /* describes vector */
169 |
170 | void v2_describe(v2_t vector)
171 | {
172 | printf("%f %f ", vector.x, vector.y);
173 | }
174 |
175 | /* returns longer side projected to x */
176 |
177 | float v2_longside(v2_t a)
178 | {
179 | float x = fabs(a.x);
180 | float y = fabs(a.y);
181 | return x > y ? x : y;
182 | }
183 |
184 | #endif
185 |
--------------------------------------------------------------------------------
/src/mt_math/mt_vector_3d.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_vector_3d_h
2 | #define mt_vector_3d_h
3 |
4 | #include
5 |
6 | typedef struct _v3_t v3_t;
7 | struct _v3_t
8 | {
9 | float x, y, z;
10 | };
11 |
12 | v3_t v3_init(float x, float y, float z);
13 | v3_t v3_add(v3_t a, v3_t b);
14 | v3_t v3_sub(v3_t a, v3_t b);
15 | v3_t v3_scale(v3_t a, float f);
16 | v3_t v3_cross(v3_t left, v3_t right);
17 | v3_t v3_normalize(v3_t matrix);
18 |
19 | v3_t v3_rotatearoundx(v3_t vector, float the_angle);
20 | v3_t v3_rotatearoundy(v3_t vector, float the_angle);
21 | v3_t v3_rotatearoundz(v3_t vector, float the_angle);
22 | v3_t v3_getxyunitrotation(v3_t vx, v3_t vy);
23 | v3_t v3_intersectwithplane(v3_t linev1, v3_t linev2, v3_t planev, v3_t planen);
24 |
25 | float v3_dot(v3_t a, v3_t b);
26 | float v3_angle(v3_t a, v3_t b);
27 | float v3_length(v3_t a);
28 | void v3_toarray(v3_t* vector, float* result);
29 | float v3_distance(v3_t vectorA, v3_t vectorB);
30 |
31 | #endif
32 | #if __INCLUDE_LEVEL__ == 0
33 |
34 | /* inits vector3 */
35 |
36 | v3_t v3_init(float x, float y, float z)
37 | {
38 | v3_t result;
39 |
40 | result.x = x;
41 | result.y = y;
42 | result.z = z;
43 |
44 | return result;
45 | }
46 |
47 | /* add two vectors */
48 |
49 | v3_t v3_add(v3_t a, v3_t b)
50 | {
51 | v3_t result;
52 |
53 | result.x = a.x + b.x;
54 | result.y = a.y + b.y;
55 | result.z = a.z + b.z;
56 |
57 | return result;
58 | }
59 |
60 | /* substracts b from a */
61 |
62 | v3_t v3_sub(v3_t a, v3_t b)
63 | {
64 | v3_t result;
65 |
66 | result.x = a.x - b.x;
67 | result.y = a.y - b.y;
68 | result.z = a.z - b.z;
69 |
70 | return result;
71 | }
72 |
73 | /* scales vector */
74 |
75 | v3_t v3_scale(v3_t a, float f)
76 | {
77 | v3_t result;
78 |
79 | result.x = a.x * f;
80 | result.y = a.y * f;
81 | result.z = a.z * f;
82 |
83 | return result;
84 | }
85 |
86 | /* creates cross product of two vectors */
87 |
88 | v3_t v3_cross(v3_t left, v3_t right)
89 | {
90 | v3_t v;
91 |
92 | v.x = left.y * right.z - left.z * right.y;
93 | v.y = left.z * right.x - left.x * right.z;
94 | v.z = left.x * right.y - left.y * right.x;
95 |
96 | return v;
97 | }
98 |
99 | /* normalizes vector */
100 |
101 | v3_t v3_normalize(v3_t matrix)
102 | {
103 | float scale;
104 |
105 | scale = 1.0f / sqrtf(matrix.x * matrix.x + matrix.y * matrix.y + matrix.z * matrix.z);
106 |
107 | matrix.x *= scale;
108 | matrix.y *= scale;
109 | matrix.z *= scale;
110 |
111 | return matrix;
112 | }
113 |
114 | /* rotates vector around it x axis */
115 |
116 | v3_t v3_rotatearoundx(v3_t vector, float the_angle)
117 | {
118 | float epsilon = 0.00001;
119 | if (fabs(vector.y) > epsilon || fabs(vector.z) > epsilon)
120 | {
121 | float angle = atan2(vector.z, vector.y);
122 | float length = sqrtf(vector.y * vector.y + vector.z * vector.z);
123 |
124 | vector.z = sin(angle + the_angle) * length;
125 | vector.y = cos(angle + the_angle) * length;
126 | }
127 | return vector;
128 | }
129 |
130 | /* rotates vector around it y axis */
131 |
132 | v3_t v3_rotatearoundy(v3_t vector, float the_angle)
133 | {
134 | float epsilon = 0.00001;
135 | if (fabs(vector.x) > epsilon || fabs(vector.z) > epsilon)
136 | {
137 | float angle = atan2(vector.z, vector.x);
138 | float length = sqrtf(vector.x * vector.x + vector.z * vector.z);
139 |
140 | vector.z = sin(angle + the_angle) * length;
141 | vector.x = cos(angle + the_angle) * length;
142 | }
143 | return vector;
144 | }
145 |
146 | /* rotates vector around it z axis */
147 |
148 | v3_t v3_rotatearoundz(v3_t vector, float the_angle)
149 | {
150 | float epsilon = 0.00001;
151 | if (fabs(vector.y) > epsilon || fabs(vector.x) > epsilon)
152 | {
153 | float angle = atan2(vector.y, vector.x);
154 | float length = sqrtf(vector.x * vector.x + vector.y * vector.y);
155 |
156 | vector.y = sin(angle + the_angle) * length;
157 | vector.x = cos(angle + the_angle) * length;
158 | }
159 | return vector;
160 | }
161 |
162 | /* rotates back plane to origo, returns rotation vector */
163 |
164 | v3_t v3_getxyunitrotation(v3_t vx, v3_t vy)
165 | {
166 | v3_t rotation;
167 |
168 | float angle;
169 | float epsilon = 0.00001;
170 |
171 | // rotate back final_x to base_x on Z axis
172 |
173 | if (fabs(vx.x) > epsilon || fabs(vx.y) > epsilon)
174 | {
175 |
176 | angle = atan2(vx.y, vx.x);
177 |
178 | rotation.z = angle;
179 |
180 | vx = v3_rotatearoundz(vx, -angle);
181 | vy = v3_rotatearoundz(vy, -angle);
182 | }
183 | else
184 | rotation.z = 0.0;
185 |
186 | // rotate back final_x to base_x on Y axis
187 |
188 | if (fabs(vx.x) > epsilon || fabs(vx.z) > epsilon)
189 | {
190 |
191 | angle = atan2(vx.z, vx.x);
192 |
193 | rotation.y = -angle;
194 |
195 | vx = v3_rotatearoundy(vx, -angle);
196 | vy = v3_rotatearoundy(vy, -angle);
197 | }
198 | else
199 | rotation.y = 0.0;
200 |
201 | // finally rotate back final_y to base_y on X axis
202 |
203 | if (fabs(vy.y) > epsilon || fabs(vy.z) > epsilon)
204 | {
205 |
206 | angle = atan2(vy.z, vy.y);
207 |
208 | rotation.x = angle;
209 |
210 | vx = v3_rotatearoundx(vx, -angle);
211 | vy = v3_rotatearoundx(vy, -angle);
212 | }
213 | else
214 | rotation.x = 0.0;
215 |
216 | return rotation;
217 | }
218 |
219 | /* intersects vector3 with plane */
220 |
221 | v3_t v3_intersectwithplane(v3_t linev1, v3_t linev2, v3_t planev, v3_t planen)
222 | {
223 | v3_t u, w, scale, result;
224 | float div;
225 |
226 | u = v3_sub(linev2, linev1);
227 | w = v3_sub(planev, linev1);
228 | div = v3_dot(planen, w) / v3_dot(planen, u);
229 | scale = v3_scale(u, div);
230 | result = v3_add(linev1, scale);
231 |
232 | return result;
233 | }
234 |
235 | /* creates dot product of two vectors */
236 |
237 | float v3_dot(v3_t a, v3_t b)
238 | {
239 | return a.x * b.x + a.y * b.y + a.z * b.z;
240 | }
241 |
242 | /* calculates angle between two vectors */
243 |
244 | float v3_angle(v3_t a, v3_t b)
245 | {
246 | return acosf(v3_dot(a, b) / (v3_length(a) * v3_length(b)));
247 | }
248 |
249 | /* calculates vector length */
250 |
251 | float v3_length(v3_t a)
252 | {
253 | return sqrtf(a.x * a.x + a.y * a.y + a.z * a.z);
254 | }
255 |
256 | /* converts vector to array */
257 |
258 | void v3_toarray(v3_t* vector, float* result)
259 | {
260 | result[0] = vector->x;
261 | result[1] = vector->y;
262 | result[2] = vector->z;
263 | }
264 |
265 | /* calculates distance of two vectors */
266 |
267 | float v3_distance(v3_t vectorA, v3_t vectorB)
268 | {
269 | float dx, dy, dz;
270 |
271 | dx = vectorB.x - vectorA.x;
272 | dy = vectorB.y - vectorA.y;
273 | dz = vectorB.z - vectorA.z;
274 |
275 | return sqrtf(dx * dx + dy * dy + dz * dz);
276 | }
277 |
278 | #endif
279 |
--------------------------------------------------------------------------------
/src/mt_math/mt_vector_4d.c:
--------------------------------------------------------------------------------
1 | #ifndef mt_vector_4d_h
2 | #define mt_vector_4d_h
3 |
4 | #include "mt_vector_3d.c"
5 |
6 | typedef struct _v4_t v4_t;
7 | struct _v4_t
8 | {
9 | float x, y, z, w;
10 | };
11 |
12 | v4_t v4_init(float x, float y, float z, float w);
13 | v4_t v4_add(v4_t a, v4_t b);
14 | v4_t v4_sub(v4_t a, v4_t b);
15 | v4_t v4_scale(v4_t a, float f);
16 | void v4_describe(v4_t vector);
17 |
18 | #endif
19 | #if __INCLUDE_LEVEL__ == 0
20 |
21 | #include
22 |
23 | /* creates vector */
24 |
25 | v4_t v4_init(float x, float y, float z, float w)
26 | {
27 | v4_t result;
28 |
29 | result.x = x;
30 | result.y = y;
31 | result.z = z;
32 | result.w = w;
33 |
34 | return result;
35 | }
36 |
37 | /* adds two vectors */
38 |
39 | v4_t v4_add(v4_t a, v4_t b)
40 | {
41 | v4_t result;
42 |
43 | result.x = a.x + b.x;
44 | result.y = a.y + b.y;
45 | result.z = a.z + b.z;
46 | result.w = a.w + b.w;
47 |
48 | return result;
49 | }
50 |
51 | /* substract b from a */
52 |
53 | v4_t v4_sub(v4_t a, v4_t b)
54 | {
55 | v4_t result;
56 |
57 | result.x = a.x - b.x;
58 | result.y = a.y - b.y;
59 | result.z = a.z - b.z;
60 | result.w = a.w - b.w;
61 |
62 | return result;
63 | }
64 |
65 | /* scales vector */
66 |
67 | v4_t v4_scale(v4_t a, float f)
68 | {
69 | v4_t result;
70 |
71 | result.x = a.x * f;
72 | result.y = a.y * f;
73 | result.z = a.z * f;
74 | result.w = a.w * f;
75 |
76 | return result;
77 | }
78 |
79 | /* describes vector4 */
80 |
81 | void v4_describe(v4_t vector)
82 | {
83 | printf("x : %f y : %f z : %f w : %f", vector.x, vector.y, vector.z, vector.w);
84 | }
85 |
86 | #endif
87 |
--------------------------------------------------------------------------------
/src/mt_math_test/mt_math_2d_test.c:
--------------------------------------------------------------------------------
1 | #include "mt_log.c"
2 |
3 | int main(int argc, char* argv[])
4 | {
5 | mt_log_set_level(MT_LOG_DEBUG);
6 |
7 | return 0;
8 | }
9 |
--------------------------------------------------------------------------------
/src/sov/draw.c:
--------------------------------------------------------------------------------
1 | #include "gen.c"
2 | #include "ku_bitmap_ext.c"
3 | #include "ku_renderer_soft.c"
4 | #include "ku_text.c"
5 | #include "mt_log.c"
6 | #include "mt_path.c"
7 | #include "mt_string.c"
8 | #include "mt_string_ext.c"
9 | #include "mt_time.c"
10 | #include "tree.c"
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | int main(int argc, char** argv)
20 | {
21 | mt_log_use_colors(isatty(STDERR_FILENO));
22 | mt_log_level_info();
23 | mt_time(NULL);
24 |
25 | /* parse options */
26 |
27 | char* cfg_par = NULL;
28 | char* tree_par = NULL;
29 | char* ws_par = NULL;
30 | char* res_par = NULL;
31 |
32 | int c, option_index = 0;
33 |
34 | static struct option long_options[] = {
35 | {"tree", required_argument, NULL, 't'},
36 | {"workspace", required_argument, NULL, 'w'},
37 | {"style", required_argument, NULL, 's'},
38 | {"result", required_argument, NULL, 'r'},
39 | };
40 |
41 | while ((c = getopt_long(argc, argv, "s:t:w:r:", long_options, &option_index)) != -1)
42 | {
43 | switch (c)
44 | {
45 | case 's': cfg_par = mt_string_new_cstring(optarg); break;
46 | case 't': tree_par = mt_string_new_cstring(optarg); break;
47 | case 'w': ws_par = mt_string_new_cstring(optarg); break;
48 | case 'r': res_par = mt_string_new_cstring(optarg); break;
49 | }
50 | }
51 |
52 | /* init config */
53 |
54 | char* cfg_path = mt_path_new_normalize(cfg_par);
55 | char* css_path = mt_path_new_append(cfg_path, "html/main.css"); // REL 6
56 | char* html_path = mt_path_new_append(cfg_path, "html/main.html"); // REL 7
57 | char* img_path = mt_path_new_append(cfg_path, "img"); // REL 6
58 |
59 | printf("style path : %s\n", cfg_path);
60 | printf("css path : %s\n", css_path);
61 | printf("html path : %s\n", html_path);
62 | printf("image path : %s\n", img_path);
63 | printf("tree path : %s\n", tree_par);
64 | printf("ws path : %s\n", ws_par);
65 | printf("res path : %s\n", res_par);
66 |
67 | /* init text rendering */
68 |
69 | ku_text_init(); // DESTROY 1
70 |
71 | /* read sway tree */
72 |
73 | char* tree_json = mt_string_new_file(tree_par);
74 | char* ws_part = mt_string_new_file(ws_par);
75 | char* ws_json = mt_string_new_cstring("{\"items\":");
76 | ws_json = mt_string_append(ws_json, ws_part);
77 | ws_json = mt_string_append(ws_json, "}");
78 |
79 | mt_vector_t* workspaces = VNEW();
80 |
81 | tree_reader_extract(ws_json, tree_json, workspaces);
82 |
83 | REL(tree_json);
84 | REL(ws_part);
85 | REL(ws_json);
86 |
87 | /* extract outputs */
88 |
89 | gen_init(html_path, css_path, img_path);
90 |
91 | int cols = 5;
92 | int rows = (int) ceilf((float) workspaces->length / cols);
93 |
94 | sway_workspace_t* ws = workspaces->data[0];
95 |
96 | int width = 0;
97 | int height = 0;
98 |
99 | gen_calc_size(
100 | ws->width / 7,
101 | ws->height / 7,
102 | 1.0,
103 | cols,
104 | rows,
105 | &width,
106 | &height);
107 |
108 | printf("WIDTH %i HEIGHT %i\n", width, height);
109 |
110 | ku_bitmap_t* bitmap = ku_bitmap_new(width, height);
111 |
112 | gen_render(
113 | ws->width / 7,
114 | ws->height / 7,
115 | 1.0,
116 | cols,
117 | rows,
118 | 0,
119 | workspaces,
120 | bitmap);
121 |
122 | bm_write(bitmap, res_par);
123 |
124 | REL(workspaces);
125 | REL(bitmap);
126 |
127 | /* cleanup */
128 |
129 | REL(ws_par);
130 | REL(res_par);
131 | REL(tree_par);
132 | if (cfg_par) REL(cfg_par);
133 | REL(cfg_path);
134 | REL(css_path);
135 | REL(html_path);
136 | REL(img_path);
137 |
138 | ku_text_destroy();
139 |
140 | #ifdef MT_MEMORY_DEBUG
141 | mt_memory_stats();
142 | #endif
143 | }
144 |
--------------------------------------------------------------------------------
/src/sov/json.c:
--------------------------------------------------------------------------------
1 | #ifndef json_h
2 | #define json_h
3 |
4 | #include "mt_vector.c"
5 |
6 | void json_parse(char* string, mt_vector_t* result);
7 |
8 | #endif
9 |
10 | #if __INCLUDE_LEVEL__ == 0
11 |
12 | #include "jsmn.c"
13 | #include "mt_memory.c"
14 | #include "mt_string.c"
15 | #include "mt_string_ext.c"
16 | #include
17 |
18 | char* json_build_path(char* string, jsmntok_t* tokens, char* path, int index)
19 | {
20 | // go to the upmost node
21 | if (tokens[index].parent > -1) path = json_build_path(string, tokens, path, tokens[index].parent);
22 | // if token is string or primitive, add to path
23 | if (tokens[index].type == JSMN_STRING || tokens[index].type == JSMN_PRIMITIVE)
24 | {
25 | path = mt_string_append(path, "/");
26 | path = mt_string_append_sub(path, string, tokens[index].start, tokens[index].end - tokens[index].start);
27 | }
28 | // if token is array, add index counter to path and increase counter
29 | if (tokens[index].type == JSMN_ARRAY)
30 | {
31 | char istr[10] = {0};
32 | snprintf(istr, 10, "/%i", tokens[index].aind);
33 | path = mt_string_append(path, istr);
34 | }
35 |
36 | return path;
37 | }
38 |
39 | /* parses c string into an map */
40 |
41 | void json_parse(char* string, mt_vector_t* result)
42 | {
43 | jsmn_parser parser;
44 |
45 | jsmn_init(&parser);
46 |
47 | int tokcount = 128;
48 | jsmntok_t* tokens = CAL(sizeof(jsmntok_t) * tokcount, NULL, NULL); // REL 0
49 | int actcount = 0;
50 |
51 | while (1)
52 | {
53 | actcount = jsmn_parse(&parser, string, strlen(string), tokens, tokcount);
54 | if (actcount != JSMN_ERROR_NOMEM)
55 | {
56 | break;
57 | }
58 | else
59 | {
60 | tokcount *= 2;
61 | tokens = mt_memory_realloc(tokens, sizeof(jsmntok_t) * tokcount);
62 | }
63 | }
64 |
65 | if (actcount > 0)
66 | {
67 | tokens[0].parent = -1;
68 |
69 | for (int index = 1; index < actcount; index++)
70 | {
71 | jsmntok_t cur_tok = tokens[index];
72 | jsmntok_t par_tok = tokens[cur_tok.parent];
73 |
74 | // printf("TOKEN index %i type %i par %i cont %s\n", index, cur_tok.type, cur_tok.parent, strndup(string + cur_tok.start, cur_tok.end - cur_tok.start));
75 |
76 | // initiate path creation and storage when needed
77 | if (cur_tok.type == JSMN_STRING || cur_tok.type == JSMN_PRIMITIVE)
78 | {
79 | if (par_tok.type == JSMN_STRING || par_tok.type == JSMN_ARRAY)
80 | {
81 | char* val = mt_string_new_cstring("");
82 | char* esc = NULL;
83 | char* key = mt_string_new_cstring("");
84 |
85 | val = mt_string_append_sub(val, string, cur_tok.start, cur_tok.end - cur_tok.start);
86 | esc = mt_string_unescape(val);
87 | REL(val);
88 | key = json_build_path(string, tokens, key, cur_tok.parent);
89 |
90 | VADDR(result, key);
91 | VADDR(result, esc);
92 |
93 | // printf("%s - %s\n", key, val);
94 | }
95 | }
96 | // increase array counters
97 | if (par_tok.type == JSMN_ARRAY)
98 | {
99 | tokens[cur_tok.parent].aind += 1;
100 | }
101 | }
102 | }
103 |
104 | REL(tokens);
105 | }
106 |
107 | #endif
108 |
--------------------------------------------------------------------------------
/src/sov/ku_bitmap_ext.c:
--------------------------------------------------------------------------------
1 | #ifndef bm_util_h
2 | #define bm_util_h
3 |
4 | #include "ku_bitmap.c"
5 | #include
6 |
7 | ku_bitmap_t* bm_new_flip_y(ku_bitmap_t* bm);
8 | void bm_write(ku_bitmap_t* bm, char* path);
9 |
10 | #endif
11 |
12 | #if __INCLUDE_LEVEL__ == 0
13 |
14 | ku_bitmap_t* bm_new_flip_y(ku_bitmap_t* bm)
15 | {
16 | ku_bitmap_t* tmp = ku_bitmap_new(bm->w, bm->h);
17 | for (int y = 0; y < bm->h; y++)
18 | {
19 | int src_y = bm->h - y - 1;
20 | memcpy(tmp->data + y * bm->w * 4, bm->data + src_y * bm->w * 4, bm->w * 4);
21 | }
22 | return tmp;
23 | }
24 |
25 | void bm_write(ku_bitmap_t* bm, char* path)
26 | {
27 | int w = bm->w;
28 | int h = bm->h;
29 |
30 | FILE* f;
31 | unsigned char* img = NULL;
32 | int filesize = 54 + 3 * w * h; // w is your image width, h is image height, both int
33 |
34 | img = (unsigned char*) malloc(3 * w * h);
35 | memset(img, 0, 3 * w * h);
36 |
37 | for (int i = 0; i < w; i++)
38 | {
39 | for (int j = 0; j < h; j++)
40 | {
41 | int index = j * w * 4 + i * 4;
42 |
43 | int x = i;
44 | int y = j;
45 |
46 | int r = bm->data[index];
47 | int g = bm->data[index + 1];
48 | int b = bm->data[index + 2];
49 |
50 | if (r > 255) r = 255;
51 | if (g > 255) g = 255;
52 | if (b > 255) b = 255;
53 |
54 | img[(x + y * w) * 3 + 2] = (unsigned char) (r);
55 | img[(x + y * w) * 3 + 1] = (unsigned char) (g);
56 | img[(x + y * w) * 3 + 0] = (unsigned char) (b);
57 | }
58 | }
59 |
60 | unsigned char bmpfileheader[14] = {'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0};
61 | unsigned char bmpinfoheader[40] = {40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0};
62 | unsigned char bmppad[3] = {0, 0, 0};
63 |
64 | bmpfileheader[2] = (unsigned char) (filesize);
65 | bmpfileheader[3] = (unsigned char) (filesize >> 8);
66 | bmpfileheader[4] = (unsigned char) (filesize >> 16);
67 | bmpfileheader[5] = (unsigned char) (filesize >> 24);
68 |
69 | bmpinfoheader[4] = (unsigned char) (w);
70 | bmpinfoheader[5] = (unsigned char) (w >> 8);
71 | bmpinfoheader[6] = (unsigned char) (w >> 16);
72 | bmpinfoheader[7] = (unsigned char) (w >> 24);
73 | bmpinfoheader[8] = (unsigned char) (h);
74 | bmpinfoheader[9] = (unsigned char) (h >> 8);
75 | bmpinfoheader[10] = (unsigned char) (h >> 16);
76 | bmpinfoheader[11] = (unsigned char) (h >> 24);
77 |
78 | f = fopen(path, "wb");
79 | fwrite(bmpfileheader, 1, 14, f);
80 | fwrite(bmpinfoheader, 1, 40, f);
81 | for (int i = 0; i < h; i++)
82 | {
83 | fwrite(img + (w * (h - i - 1) * 3), 3, w, f);
84 | fwrite(bmppad, 1, (4 - (w * 3) % 4) % 4, f);
85 | }
86 |
87 | free(img);
88 | fclose(f);
89 | }
90 |
91 | #endif
92 |
--------------------------------------------------------------------------------
/tst/a_workspace.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 4,
4 | "type": "workspace",
5 | "orientation": "horizontal",
6 | "percent": null,
7 | "urgent": false,
8 | "marks": [],
9 | "layout": "splith",
10 | "border": "none",
11 | "current_border_width": 0,
12 | "rect": {
13 | "x": 5,
14 | "y": 29,
15 | "width": 1910,
16 | "height": 1046
17 | },
18 | "deco_rect": {
19 | "x": 0,
20 | "y": 0,
21 | "width": 0,
22 | "height": 0
23 | },
24 | "window_rect": {
25 | "x": 0,
26 | "y": 0,
27 | "width": 0,
28 | "height": 0
29 | },
30 | "geometry": {
31 | "x": 0,
32 | "y": 0,
33 | "width": 0,
34 | "height": 0
35 | },
36 | "name": "1",
37 | "window": null,
38 | "nodes": [],
39 | "floating_nodes": [],
40 | "focus": [
41 | 62
42 | ],
43 | "fullscreen_mode": 1,
44 | "sticky": false,
45 | "num": 1,
46 | "output": "eDP-1",
47 | "representation": "H[V[foot foot]]",
48 | "focused": true,
49 | "visible": true
50 | },
51 | {
52 | "id": 6,
53 | "type": "workspace",
54 | "orientation": "horizontal",
55 | "percent": null,
56 | "urgent": false,
57 | "marks": [],
58 | "layout": "splith",
59 | "border": "none",
60 | "current_border_width": 0,
61 | "rect": {
62 | "x": 5,
63 | "y": 29,
64 | "width": 1910,
65 | "height": 1046
66 | },
67 | "deco_rect": {
68 | "x": 0,
69 | "y": 0,
70 | "width": 0,
71 | "height": 0
72 | },
73 | "window_rect": {
74 | "x": 0,
75 | "y": 0,
76 | "width": 0,
77 | "height": 0
78 | },
79 | "geometry": {
80 | "x": 0,
81 | "y": 0,
82 | "width": 0,
83 | "height": 0
84 | },
85 | "name": "2",
86 | "window": null,
87 | "nodes": [],
88 | "floating_nodes": [],
89 | "focus": [
90 | 7
91 | ],
92 | "fullscreen_mode": 1,
93 | "sticky": false,
94 | "num": 2,
95 | "output": "eDP-1",
96 | "representation": "H[foot]",
97 | "focused": false,
98 | "visible": false
99 | },
100 | {
101 | "id": 64,
102 | "type": "workspace",
103 | "orientation": "horizontal",
104 | "percent": null,
105 | "urgent": false,
106 | "marks": [],
107 | "layout": "splith",
108 | "border": "none",
109 | "current_border_width": 0,
110 | "rect": {
111 | "x": 5,
112 | "y": 29,
113 | "width": 1910,
114 | "height": 1046
115 | },
116 | "deco_rect": {
117 | "x": 0,
118 | "y": 0,
119 | "width": 0,
120 | "height": 0
121 | },
122 | "window_rect": {
123 | "x": 0,
124 | "y": 0,
125 | "width": 0,
126 | "height": 0
127 | },
128 | "geometry": {
129 | "x": 0,
130 | "y": 0,
131 | "width": 0,
132 | "height": 0
133 | },
134 | "name": "3",
135 | "window": null,
136 | "nodes": [],
137 | "floating_nodes": [],
138 | "focus": [
139 | 9
140 | ],
141 | "fullscreen_mode": 1,
142 | "sticky": false,
143 | "num": 3,
144 | "output": "eDP-1",
145 | "representation": "H[google-chrome]",
146 | "focused": false,
147 | "visible": false
148 | },
149 | {
150 | "id": 12,
151 | "type": "workspace",
152 | "orientation": "horizontal",
153 | "percent": null,
154 | "urgent": false,
155 | "marks": [],
156 | "layout": "splith",
157 | "border": "none",
158 | "current_border_width": 0,
159 | "rect": {
160 | "x": 5,
161 | "y": 29,
162 | "width": 1910,
163 | "height": 1046
164 | },
165 | "deco_rect": {
166 | "x": 0,
167 | "y": 0,
168 | "width": 0,
169 | "height": 0
170 | },
171 | "window_rect": {
172 | "x": 0,
173 | "y": 0,
174 | "width": 0,
175 | "height": 0
176 | },
177 | "geometry": {
178 | "x": 0,
179 | "y": 0,
180 | "width": 0,
181 | "height": 0
182 | },
183 | "name": "4",
184 | "window": null,
185 | "nodes": [],
186 | "floating_nodes": [],
187 | "focus": [
188 | 10,
189 | 11
190 | ],
191 | "fullscreen_mode": 1,
192 | "sticky": false,
193 | "num": 4,
194 | "output": "eDP-1",
195 | "representation": "H[google-chrome google-chrome]",
196 | "focused": false,
197 | "visible": false
198 | },
199 | {
200 | "id": 88,
201 | "type": "workspace",
202 | "orientation": "horizontal",
203 | "percent": null,
204 | "urgent": false,
205 | "marks": [],
206 | "layout": "splith",
207 | "border": "none",
208 | "current_border_width": 0,
209 | "rect": {
210 | "x": 5,
211 | "y": 29,
212 | "width": 1910,
213 | "height": 1046
214 | },
215 | "deco_rect": {
216 | "x": 0,
217 | "y": 0,
218 | "width": 0,
219 | "height": 0
220 | },
221 | "window_rect": {
222 | "x": 0,
223 | "y": 0,
224 | "width": 0,
225 | "height": 0
226 | },
227 | "geometry": {
228 | "x": 0,
229 | "y": 0,
230 | "width": 0,
231 | "height": 0
232 | },
233 | "name": "5",
234 | "window": null,
235 | "nodes": [],
236 | "floating_nodes": [],
237 | "focus": [
238 | 89
239 | ],
240 | "fullscreen_mode": 1,
241 | "sticky": false,
242 | "num": 5,
243 | "output": "eDP-1",
244 | "representation": "H[foot]",
245 | "focused": false,
246 | "visible": false
247 | }
248 | ]
249 |
--------------------------------------------------------------------------------
/tst/empty_6_workspace.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 7,
4 | "type": "workspace",
5 | "orientation": "horizontal",
6 | "percent": null,
7 | "urgent": false,
8 | "marks": [
9 | ],
10 | "layout": "splith",
11 | "border": "none",
12 | "current_border_width": 0,
13 | "rect": {
14 | "x": 5,
15 | "y": 29,
16 | "width": 1014,
17 | "height": 734
18 | },
19 | "deco_rect": {
20 | "x": 0,
21 | "y": 0,
22 | "width": 0,
23 | "height": 0
24 | },
25 | "window_rect": {
26 | "x": 0,
27 | "y": 0,
28 | "width": 0,
29 | "height": 0
30 | },
31 | "geometry": {
32 | "x": 0,
33 | "y": 0,
34 | "width": 0,
35 | "height": 0
36 | },
37 | "name": "6",
38 | "window": null,
39 | "nodes": [
40 | ],
41 | "floating_nodes": [
42 | ],
43 | "focus": [
44 | ],
45 | "fullscreen_mode": 1,
46 | "sticky": false,
47 | "num": 6,
48 | "output": "Virtual-1",
49 | "representation": null,
50 | "focused": true,
51 | "visible": true
52 | }
53 | ]
54 |
--------------------------------------------------------------------------------
/tst/empty_tree.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 1,
3 | "type": "root",
4 | "orientation": "horizontal",
5 | "percent": null,
6 | "urgent": false,
7 | "marks": [],
8 | "focused": false,
9 | "layout": "splith",
10 | "border": "none",
11 | "current_border_width": 0,
12 | "rect": {
13 | "x": 0,
14 | "y": 0,
15 | "width": 1920,
16 | "height": 1080
17 | },
18 | "deco_rect": {
19 | "x": 0,
20 | "y": 0,
21 | "width": 0,
22 | "height": 0
23 | },
24 | "window_rect": {
25 | "x": 0,
26 | "y": 0,
27 | "width": 0,
28 | "height": 0
29 | },
30 | "geometry": {
31 | "x": 0,
32 | "y": 0,
33 | "width": 0,
34 | "height": 0
35 | },
36 | "name": "root",
37 | "window": null,
38 | "nodes": [
39 | {
40 | "id": 2147483647,
41 | "type": "output",
42 | "orientation": "horizontal",
43 | "percent": null,
44 | "urgent": false,
45 | "marks": [],
46 | "focused": false,
47 | "layout": "output",
48 | "border": "none",
49 | "current_border_width": 0,
50 | "rect": {
51 | "x": 0,
52 | "y": 0,
53 | "width": 1920,
54 | "height": 1080
55 | },
56 | "deco_rect": {
57 | "x": 0,
58 | "y": 0,
59 | "width": 0,
60 | "height": 0
61 | },
62 | "window_rect": {
63 | "x": 0,
64 | "y": 0,
65 | "width": 0,
66 | "height": 0
67 | },
68 | "geometry": {
69 | "x": 0,
70 | "y": 0,
71 | "width": 0,
72 | "height": 0
73 | },
74 | "name": "__i3",
75 | "window": null,
76 | "nodes": [
77 | {
78 | "id": 2147483646,
79 | "type": "workspace",
80 | "orientation": "horizontal",
81 | "percent": null,
82 | "urgent": false,
83 | "marks": [],
84 | "focused": false,
85 | "layout": "splith",
86 | "border": "none",
87 | "current_border_width": 0,
88 | "rect": {
89 | "x": 0,
90 | "y": 0,
91 | "width": 1920,
92 | "height": 1080
93 | },
94 | "deco_rect": {
95 | "x": 0,
96 | "y": 0,
97 | "width": 0,
98 | "height": 0
99 | },
100 | "window_rect": {
101 | "x": 0,
102 | "y": 0,
103 | "width": 0,
104 | "height": 0
105 | },
106 | "geometry": {
107 | "x": 0,
108 | "y": 0,
109 | "width": 0,
110 | "height": 0
111 | },
112 | "name": "__i3_scratch",
113 | "window": null,
114 | "nodes": [],
115 | "floating_nodes": [],
116 | "focus": [],
117 | "fullscreen_mode": 1,
118 | "sticky": false
119 | }
120 | ],
121 | "floating_nodes": [],
122 | "focus": [
123 | 2147483646
124 | ],
125 | "fullscreen_mode": 0,
126 | "sticky": false
127 | },
128 | {
129 | "id": 3,
130 | "type": "output",
131 | "orientation": "none",
132 | "percent": 1,
133 | "urgent": false,
134 | "marks": [],
135 | "focused": false,
136 | "layout": "output",
137 | "border": "none",
138 | "current_border_width": 0,
139 | "rect": {
140 | "x": 0,
141 | "y": 0,
142 | "width": 1920,
143 | "height": 1080
144 | },
145 | "deco_rect": {
146 | "x": 0,
147 | "y": 0,
148 | "width": 0,
149 | "height": 0
150 | },
151 | "window_rect": {
152 | "x": 0,
153 | "y": 0,
154 | "width": 0,
155 | "height": 0
156 | },
157 | "geometry": {
158 | "x": 0,
159 | "y": 0,
160 | "width": 0,
161 | "height": 0
162 | },
163 | "name": "eDP-1",
164 | "window": null,
165 | "nodes": [
166 | {
167 | "id": 4,
168 | "type": "workspace",
169 | "orientation": "horizontal",
170 | "percent": null,
171 | "urgent": false,
172 | "marks": [],
173 | "focused": true,
174 | "layout": "splith",
175 | "border": "none",
176 | "current_border_width": 0,
177 | "rect": {
178 | "x": 5,
179 | "y": 29,
180 | "width": 1910,
181 | "height": 1046
182 | },
183 | "deco_rect": {
184 | "x": 0,
185 | "y": 0,
186 | "width": 0,
187 | "height": 0
188 | },
189 | "window_rect": {
190 | "x": 0,
191 | "y": 0,
192 | "width": 0,
193 | "height": 0
194 | },
195 | "geometry": {
196 | "x": 0,
197 | "y": 0,
198 | "width": 0,
199 | "height": 0
200 | },
201 | "name": "1",
202 | "window": null,
203 | "nodes": [],
204 | "floating_nodes": [],
205 | "focus": [],
206 | "fullscreen_mode": 1,
207 | "sticky": false,
208 | "num": 1,
209 | "output": "eDP-1",
210 | "representation": "H[]"
211 | }
212 | ],
213 | "floating_nodes": [],
214 | "focus": [
215 | 4
216 | ],
217 | "fullscreen_mode": 0,
218 | "sticky": false,
219 | "active": true,
220 | "dpms": true,
221 | "primary": false,
222 | "make": "Unknown",
223 | "model": "0x0700",
224 | "serial": "0x00000000",
225 | "scale": 1,
226 | "scale_filter": "nearest",
227 | "transform": "normal",
228 | "adaptive_sync_status": "disabled",
229 | "current_workspace": "1",
230 | "modes": [
231 | {
232 | "width": 1920,
233 | "height": 1080,
234 | "refresh": 60027
235 | }
236 | ],
237 | "current_mode": {
238 | "width": 1920,
239 | "height": 1080,
240 | "refresh": 60027
241 | },
242 | "max_render_time": 0
243 | }
244 | ],
245 | "floating_nodes": [],
246 | "focus": [
247 | 3
248 | ],
249 | "fullscreen_mode": 0,
250 | "sticky": false
251 | }
252 |
--------------------------------------------------------------------------------
/tst/empty_workspace.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 4,
4 | "type": "workspace",
5 | "orientation": "horizontal",
6 | "percent": null,
7 | "urgent": false,
8 | "marks": [],
9 | "layout": "splith",
10 | "border": "none",
11 | "current_border_width": 0,
12 | "rect": {
13 | "x": 5,
14 | "y": 29,
15 | "width": 1910,
16 | "height": 1046
17 | },
18 | "deco_rect": {
19 | "x": 0,
20 | "y": 0,
21 | "width": 0,
22 | "height": 0
23 | },
24 | "window_rect": {
25 | "x": 0,
26 | "y": 0,
27 | "width": 0,
28 | "height": 0
29 | },
30 | "geometry": {
31 | "x": 0,
32 | "y": 0,
33 | "width": 0,
34 | "height": 0
35 | },
36 | "name": "1",
37 | "window": null,
38 | "nodes": [],
39 | "floating_nodes": [],
40 | "focus": [],
41 | "fullscreen_mode": 1,
42 | "sticky": false,
43 | "num": 1,
44 | "output": "eDP-1",
45 | "representation": "H[]",
46 | "focused": true,
47 | "visible": true
48 | }
49 | ]
50 |
--------------------------------------------------------------------------------
/tst/feh_workspace.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 78,
4 | "type": "workspace",
5 | "orientation": "horizontal",
6 | "percent": null,
7 | "urgent": false,
8 | "marks": [],
9 | "layout": "splith",
10 | "border": "none",
11 | "current_border_width": 0,
12 | "rect": {
13 | "x": 5,
14 | "y": 29,
15 | "width": 1910,
16 | "height": 1046
17 | },
18 | "deco_rect": {
19 | "x": 0,
20 | "y": 0,
21 | "width": 0,
22 | "height": 0
23 | },
24 | "window_rect": {
25 | "x": 0,
26 | "y": 0,
27 | "width": 0,
28 | "height": 0
29 | },
30 | "geometry": {
31 | "x": 0,
32 | "y": 0,
33 | "width": 0,
34 | "height": 0
35 | },
36 | "name": "1",
37 | "window": null,
38 | "nodes": [],
39 | "floating_nodes": [],
40 | "focus": [
41 | 79
42 | ],
43 | "fullscreen_mode": 1,
44 | "sticky": false,
45 | "num": 1,
46 | "output": "eDP-1",
47 | "representation": "H[foot]",
48 | "focused": false,
49 | "visible": false
50 | },
51 | {
52 | "id": 88,
53 | "type": "workspace",
54 | "orientation": "horizontal",
55 | "percent": null,
56 | "urgent": false,
57 | "marks": [],
58 | "layout": "splith",
59 | "border": "none",
60 | "current_border_width": 0,
61 | "rect": {
62 | "x": 5,
63 | "y": 29,
64 | "width": 1910,
65 | "height": 1046
66 | },
67 | "deco_rect": {
68 | "x": 0,
69 | "y": 0,
70 | "width": 0,
71 | "height": 0
72 | },
73 | "window_rect": {
74 | "x": 0,
75 | "y": 0,
76 | "width": 0,
77 | "height": 0
78 | },
79 | "geometry": {
80 | "x": 0,
81 | "y": 0,
82 | "width": 0,
83 | "height": 0
84 | },
85 | "name": "2",
86 | "window": null,
87 | "nodes": [],
88 | "floating_nodes": [
89 | {
90 | "id": 131,
91 | "type": "floating_con",
92 | "orientation": "none",
93 | "percent": 0.11146927212116965,
94 | "urgent": false,
95 | "marks": [],
96 | "focused": true,
97 | "layout": "none",
98 | "border": "none",
99 | "current_border_width": 2,
100 | "rect": {
101 | "x": 305,
102 | "y": 467,
103 | "width": 1310,
104 | "height": 170
105 | },
106 | "deco_rect": {
107 | "x": 0,
108 | "y": 0,
109 | "width": 0,
110 | "height": 0
111 | },
112 | "window_rect": {
113 | "x": 0,
114 | "y": 0,
115 | "width": 1310,
116 | "height": 170
117 | },
118 | "geometry": {
119 | "x": 0,
120 | "y": 0,
121 | "width": 1310,
122 | "height": 170
123 | },
124 | "name": "feh [14 of 18] - tst/tst_image_floating_a.bmp",
125 | "window": 4194305,
126 | "nodes": [],
127 | "floating_nodes": [],
128 | "focus": [],
129 | "fullscreen_mode": 0,
130 | "sticky": false,
131 | "pid": 142334,
132 | "app_id": null,
133 | "visible": true,
134 | "max_render_time": 0,
135 | "shell": "xwayland",
136 | "inhibit_idle": false,
137 | "idle_inhibitors": {
138 | "user": "none",
139 | "application": "none"
140 | },
141 | "window_properties": {
142 | "class": "feh",
143 | "instance": "feh",
144 | "title": "feh [14 of 18] - tst/tst_image_floating_a.bmp",
145 | "transient_for": null
146 | }
147 | }
148 | ],
149 | "focus": [
150 | 131,
151 | 129,
152 | 124
153 | ],
154 | "fullscreen_mode": 1,
155 | "sticky": false,
156 | "num": 2,
157 | "output": "eDP-1",
158 | "representation": "H[foot foot]",
159 | "focused": true,
160 | "visible": true
161 | },
162 | {
163 | "id": 70,
164 | "type": "workspace",
165 | "orientation": "horizontal",
166 | "percent": null,
167 | "urgent": false,
168 | "marks": [],
169 | "layout": "splith",
170 | "border": "none",
171 | "current_border_width": 0,
172 | "rect": {
173 | "x": 5,
174 | "y": 29,
175 | "width": 1910,
176 | "height": 1046
177 | },
178 | "deco_rect": {
179 | "x": 0,
180 | "y": 0,
181 | "width": 0,
182 | "height": 0
183 | },
184 | "window_rect": {
185 | "x": 0,
186 | "y": 0,
187 | "width": 0,
188 | "height": 0
189 | },
190 | "geometry": {
191 | "x": 0,
192 | "y": 0,
193 | "width": 0,
194 | "height": 0
195 | },
196 | "name": "3",
197 | "window": null,
198 | "nodes": [],
199 | "floating_nodes": [],
200 | "focus": [
201 | 72
202 | ],
203 | "fullscreen_mode": 1,
204 | "sticky": false,
205 | "num": 3,
206 | "output": "eDP-1",
207 | "representation": "H[google-chrome]",
208 | "focused": false,
209 | "visible": false
210 | },
211 | {
212 | "id": 74,
213 | "type": "workspace",
214 | "orientation": "horizontal",
215 | "percent": null,
216 | "urgent": false,
217 | "marks": [],
218 | "layout": "splith",
219 | "border": "none",
220 | "current_border_width": 0,
221 | "rect": {
222 | "x": 5,
223 | "y": 29,
224 | "width": 1910,
225 | "height": 1046
226 | },
227 | "deco_rect": {
228 | "x": 0,
229 | "y": 0,
230 | "width": 0,
231 | "height": 0
232 | },
233 | "window_rect": {
234 | "x": 0,
235 | "y": 0,
236 | "width": 0,
237 | "height": 0
238 | },
239 | "geometry": {
240 | "x": 0,
241 | "y": 0,
242 | "width": 0,
243 | "height": 0
244 | },
245 | "name": "4",
246 | "window": null,
247 | "nodes": [],
248 | "floating_nodes": [],
249 | "focus": [
250 | 73
251 | ],
252 | "fullscreen_mode": 1,
253 | "sticky": false,
254 | "num": 4,
255 | "output": "eDP-1",
256 | "representation": "H[google-chrome]",
257 | "focused": false,
258 | "visible": false
259 | }
260 | ]
261 |
--------------------------------------------------------------------------------
/tst/floating_workspace.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 4,
4 | "type": "workspace",
5 | "orientation": "horizontal",
6 | "percent": null,
7 | "urgent": false,
8 | "marks": [],
9 | "layout": "splith",
10 | "border": "none",
11 | "current_border_width": 0,
12 | "rect": {
13 | "x": 5,
14 | "y": 29,
15 | "width": 1910,
16 | "height": 1046
17 | },
18 | "deco_rect": {
19 | "x": 0,
20 | "y": 0,
21 | "width": 0,
22 | "height": 0
23 | },
24 | "window_rect": {
25 | "x": 0,
26 | "y": 0,
27 | "width": 0,
28 | "height": 0
29 | },
30 | "geometry": {
31 | "x": 0,
32 | "y": 0,
33 | "width": 0,
34 | "height": 0
35 | },
36 | "name": "1",
37 | "window": null,
38 | "nodes": [],
39 | "floating_nodes": [
40 | {
41 | "id": 65,
42 | "type": "floating_con",
43 | "orientation": "none",
44 | "percent": 0.17639073808975606,
45 | "urgent": false,
46 | "marks": [],
47 | "focused": true,
48 | "layout": "none",
49 | "border": "pixel",
50 | "current_border_width": 1,
51 | "rect": {
52 | "x": 609,
53 | "y": 301,
54 | "width": 702,
55 | "height": 502
56 | },
57 | "deco_rect": {
58 | "x": 0,
59 | "y": 0,
60 | "width": 0,
61 | "height": 0
62 | },
63 | "window_rect": {
64 | "x": 1,
65 | "y": 1,
66 | "width": 700,
67 | "height": 500
68 | },
69 | "geometry": {
70 | "x": 0,
71 | "y": 0,
72 | "width": 700,
73 | "height": 500
74 | },
75 | "name": "mc [milgra@milgra-pc]:~/Downloads",
76 | "window": null,
77 | "nodes": [],
78 | "floating_nodes": [],
79 | "focus": [],
80 | "fullscreen_mode": 0,
81 | "sticky": false,
82 | "pid": 105884,
83 | "app_id": "foot",
84 | "visible": true,
85 | "max_render_time": 0,
86 | "shell": "xdg_shell",
87 | "inhibit_idle": false,
88 | "idle_inhibitors": {
89 | "user": "none",
90 | "application": "none"
91 | }
92 | }
93 | ],
94 | "focus": [
95 | 65
96 | ],
97 | "fullscreen_mode": 1,
98 | "sticky": false,
99 | "num": 1,
100 | "output": "eDP-1",
101 | "representation": "H[]",
102 | "focused": true,
103 | "visible": true
104 | }
105 | ]
106 |
--------------------------------------------------------------------------------
/tst/master/a_result_a.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/a_result_a.bmp
--------------------------------------------------------------------------------
/tst/master/a_result_b.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/a_result_b.bmp
--------------------------------------------------------------------------------
/tst/master/b_result_a.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/b_result_a.bmp
--------------------------------------------------------------------------------
/tst/master/b_result_b.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/b_result_b.bmp
--------------------------------------------------------------------------------
/tst/master/empty_6_result_a.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/empty_6_result_a.bmp
--------------------------------------------------------------------------------
/tst/master/empty_6_result_b.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/empty_6_result_b.bmp
--------------------------------------------------------------------------------
/tst/master/empty_result_a.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/empty_result_a.bmp
--------------------------------------------------------------------------------
/tst/master/empty_result_b.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/empty_result_b.bmp
--------------------------------------------------------------------------------
/tst/master/feh_result_a.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/feh_result_a.bmp
--------------------------------------------------------------------------------
/tst/master/feh_result_b.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/feh_result_b.bmp
--------------------------------------------------------------------------------
/tst/master/floating_result_a.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/floating_result_a.bmp
--------------------------------------------------------------------------------
/tst/master/floating_result_b.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/floating_result_b.bmp
--------------------------------------------------------------------------------
/tst/master/rotated_result_a.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/rotated_result_a.bmp
--------------------------------------------------------------------------------
/tst/master/rotated_result_b.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/milgra/sov/19809ae535f8417098020f86ceefa25dbd3c5a90/tst/master/rotated_result_b.bmp
--------------------------------------------------------------------------------
/tst/runtests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | exe="$1/draw"
4 |
5 | mkdir -p tst/result
6 |
7 | $exe -s tst/stylea -t tst/a_tree.json -w tst/a_workspace.json -r tst/result/a_result_a.bmp
8 | $exe -s tst/styleb -t tst/a_tree.json -w tst/a_workspace.json -r tst/result/a_result_b.bmp
9 |
10 | $exe -s tst/stylea -t tst/b_tree.json -w tst/b_workspace.json -r tst/result/b_result_a.bmp
11 | $exe -s tst/styleb -t tst/b_tree.json -w tst/b_workspace.json -r tst/result/b_result_b.bmp
12 |
13 | $exe -s tst/stylea -t tst/empty_tree.json -w tst/empty_workspace.json -r tst/result/empty_result_a.bmp
14 | $exe -s tst/styleb -t tst/empty_tree.json -w tst/empty_workspace.json -r tst/result/empty_result_b.bmp
15 |
16 | $exe -s tst/stylea -t tst/empty_6_tree.json -w tst/empty_6_workspace.json -r tst/result/empty_6_result_a.bmp
17 | $exe -s tst/styleb -t tst/empty_6_tree.json -w tst/empty_6_workspace.json -r tst/result/empty_6_result_b.bmp
18 |
19 | $exe -s tst/stylea -t tst/feh_tree.json -w tst/feh_workspace.json -r tst/result/feh_result_a.bmp
20 | $exe -s tst/styleb -t tst/feh_tree.json -w tst/feh_workspace.json -r tst/result/feh_result_b.bmp
21 |
22 | $exe -s tst/stylea -t tst/floating_tree.json -w tst/floating_workspace.json -r tst/result/floating_result_a.bmp
23 | $exe -s tst/styleb -t tst/floating_tree.json -w tst/floating_workspace.json -r tst/result/floating_result_b.bmp
24 |
25 | $exe -s tst/stylea -t tst/rotated_tree.json -w tst/rotated_workspace.json -r tst/result/rotated_result_a.bmp
26 | $exe -s tst/styleb -t tst/rotated_tree.json -w tst/rotated_workspace.json -r tst/result/rotated_result_b.bmp
27 |
28 | diff tst/master tst/result
29 |
30 | error=$?
31 | if [ $error -eq 0 ]
32 | then
33 | echo "No differences found between master and result images"
34 | exit 0
35 | elif [ $error -eq 1 ]
36 | then
37 | echo "Differences found between master and result images"
38 | exit 1
39 | else
40 | echo "Differences found between master and result images"
41 | exit 1
42 | fi
43 |
--------------------------------------------------------------------------------
/tst/stylea/html/main.css:
--------------------------------------------------------------------------------
1 | #main {
2 | border-radius: 10px;
3 | background-color: #00000044;
4 | }
5 |
6 | #base {
7 | margin: 15px;
8 | }
9 |
10 | .fullscale {
11 | height: 100%;
12 | width: 100%;
13 | }
14 |
15 | .colflex {
16 | display: flex;
17 | flex-direction: column;
18 | }
19 |
20 | .rowflex {
21 | display: flex;
22 | flex-direction: row;
23 | }
24 |
25 | .workspace {
26 | margin: 10px;
27 | border-radius: 8px;
28 | background-color: #000000FF;
29 | border-width: 1px;
30 | border-color: #555555FF;
31 | }
32 |
33 | .window {
34 | width: 100px;
35 | height: 80px;
36 | background-color: #222222FF;
37 | border-radius: 8px;
38 | border-width: 1px;
39 | border-color: #BCBCBCFF;
40 | }
41 |
42 | .window_active {
43 | width: 100px;
44 | height: 80px;
45 | background-color: #444444FF;
46 | border-radius: 8px;
47 | border-width: 1px;
48 | border-color: #BCBCBCFF;
49 | }
50 |
51 | .title {
52 | width: 100%;
53 | height: 21px;
54 | margin-top: 4px;
55 | margin-left: 4px;
56 | color: #FFFFFFFF;
57 | font-size: 14px;
58 | font-family: "Liberation Mono:style=Bold";
59 | }
60 |
61 | .content {
62 | width: 100%;
63 | height: 100%;
64 | margin-left: 4px;
65 | color: #999999FF;
66 | vertical-align: top;
67 | font-size: 12px;
68 | font-family: "Liberation Mono:style=Bold";
69 | word-wrap: break-word;
70 | line-height: 12px;
71 | }
72 |
73 | .number {
74 | width: 20px;
75 | height: 20px;
76 | right: -14px;
77 | top: -9px;
78 | color: #FFFFFFFF;
79 | font-size: 18px;
80 | font-family: "Liberation Mono:style=Bold";
81 | }
82 |
--------------------------------------------------------------------------------
/tst/stylea/html/main.html:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
--------------------------------------------------------------------------------
/tst/styleb/html/main.css:
--------------------------------------------------------------------------------
1 | #main {
2 | border-radius: 5px;
3 | background-color: #55006688;
4 | }
5 |
6 | #base {
7 | margin: 10px;
8 | }
9 |
10 | .fullscale {
11 | height: 100%;
12 | width: 100%;
13 | }
14 |
15 | .colflex {
16 | display: flex;
17 | flex-direction: column;
18 | }
19 |
20 | .rowflex {
21 | display: flex;
22 | flex-direction: row;
23 | }
24 |
25 | .workspace {
26 | margin: 5px;
27 | background-color: #000000FF;
28 | border-width: 1px;
29 | border-color: #555555FF;
30 | }
31 |
32 | .window {
33 | width: 100px;
34 | height: 80px;
35 | background-color: #222255BB;
36 | border-width: 1px;
37 | border-color: #BCBCBCFF;
38 | }
39 |
40 | .window_active {
41 | width: 100px;
42 | height: 80px;
43 | background-color: #444444FF;
44 | border-width: 1px;
45 | border-color: #BCBCBCFF;
46 | }
47 |
48 | .title {
49 | width: 100%;
50 | height: 25px;
51 | margin-top: 4px;
52 | margin-left: 4px;
53 | color: #FFFFFFFF;
54 | font-size: 14px;
55 | font-family: "Liberation Serif:style=Italic";
56 | }
57 |
58 | .content {
59 | width: 100%;
60 | height: 100%;
61 | margin-left: 4px;
62 | color: #999999FF;
63 | vertical-align: top;
64 | font-size: 12px;
65 | font-family: "Liberation Serif:style=Italic";
66 | word-wrap: break-word;
67 | line-height: 12px;
68 | }
69 |
70 | .number {
71 | width: 20px;
72 | height: 20px;
73 | right: -14px;
74 | top: -9px;
75 | color: #FFFFFFFF;
76 | font-size: 18px;
77 | font-family: "Liberation Serif:style=Italic";
78 | }
79 |
--------------------------------------------------------------------------------
/tst/styleb/html/main.html:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
--------------------------------------------------------------------------------