add libharu binding and basic harfbuzz binding
This commit is contained in:
parent
62f7045fce
commit
02b9e82747
16 changed files with 309 additions and 7 deletions
23
LICENSE-MIT
Normal file
23
LICENSE-MIT
Normal file
|
@ -0,0 +1,23 @@
|
|||
uahgi2
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 chenjt30
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
7
README.md
Normal file
7
README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
uahgi2
|
||||
======
|
||||
README text here.
|
||||
|
||||
## Dependencies
|
||||
- Racket 8.10
|
||||
- fontconfig (for its `fc-match`)
|
5
fonts/LICENSE
Normal file
5
fonts/LICENSE
Normal file
|
@ -0,0 +1,5 @@
|
|||
NotoSerifCJKtc-VF.ttf and NotoSansCJKtc-VF.ttf are under
|
||||
under Open Font License https://openfontlicense.org/
|
||||
from https://github.com/notofonts/
|
||||
|
||||
|
BIN
fonts/NotoSansCJKtc-VF.ttf
Normal file
BIN
fonts/NotoSansCJKtc-VF.ttf
Normal file
Binary file not shown.
BIN
fonts/NotoSerifCJKtc-VF.ttf
Normal file
BIN
fonts/NotoSerifCJKtc-VF.ttf
Normal file
Binary file not shown.
9
info.rkt
Normal file
9
info.rkt
Normal file
|
@ -0,0 +1,9 @@
|
|||
#lang info
|
||||
(define collection "uahgi2")
|
||||
(define deps '("base"))
|
||||
(define build-deps '("scribble-lib" "racket-doc" "rackunit-lib"))
|
||||
(define scribblings '(("scribblings/uahgi2.scrbl" ())))
|
||||
(define pkg-desc "Description Here")
|
||||
(define version "0.0")
|
||||
(define pkg-authors '(chenjt30))
|
||||
(define license '(Apache-2.0 OR MIT))
|
|
@ -2,7 +2,8 @@
|
|||
(require "lexer.rkt" brag/support rackunit)
|
||||
|
||||
(define (lex str)
|
||||
(apply-port-proc basic-lexer str))
|
||||
(apply-port-proc uahgi2-lexer str))
|
||||
|
||||
(lex "@a123")
|
||||
(lex "{@_a12|foo|123.12}123abc\\@\\{mn̂g他@@愛@@貓,也愛這塊土地%註解%。這也是%%。")
|
||||
(lex "|測試}abc")
|
|
@ -5,7 +5,7 @@
|
|||
(define-lex-abbrev raw-id (:: (:or "_" (:/ "a" "z") (:/ "A" "Z")) (:* (:or "_" (:/ "0" "9") (:/ "a" "z") (:/ "A" "Z")))))
|
||||
(define-lex-abbrev any-other-char (:~ (char-set "0123456789@\\{}%|")))
|
||||
|
||||
(define basic-lexer
|
||||
(define uahgi2-lexer
|
||||
(lexer-srcloc
|
||||
[(:or "\r\n" "\n") (token 'NEWLINE lexeme)] ; newline
|
||||
[whitespace (token lexeme #:skip? #t)] ; whitespace
|
||||
|
@ -17,10 +17,11 @@
|
|||
["}" (token 'R_PAREN lexeme)] ; }
|
||||
["|" (token 'SEPERATOR lexeme)] ; | (general) seperator
|
||||
["@@" (token 'G_SEPERATOR lexeme)] ; @@ great seperator
|
||||
["`" (token 'NUM_CONVERTER lexeme)] ; ` convert to number
|
||||
[digits (token 'INTEGER (string->number lexeme))] ;123
|
||||
[(:: (:? (char-set "-")) digits "." digits) ; 123.456
|
||||
(token 'DECIMAL (string->number lexeme))]
|
||||
[ (from/to "%" "%") ; %COMMENT%
|
||||
(token 'COMMENT #:skip? #t)]
|
||||
[any-other-char (token 'CHAR lexeme)])) ; any char into char
|
||||
(provide basic-lexer)
|
||||
(provide uahgi2-lexer)
|
13
parser-test.rkt
Normal file
13
parser-test.rkt
Normal file
|
@ -0,0 +1,13 @@
|
|||
#lang br
|
||||
(require uahgi2/parser uahgi2/tokenizer brag/support)
|
||||
(define str #<<Here
|
||||
{@set|@paperwidth|`2100}
|
||||
{@set|@paperheight|`2970}
|
||||
{@set|@textsize|`12.3}
|
||||
{@maintext@@
|
||||
{@hd2|我是貓 I'm a cat}天地人123
|
||||
}
|
||||
Here
|
||||
)
|
||||
|
||||
(parse-to-datum (apply-tokenizer make-tokenizer str))
|
17
parser.rkt
Normal file
17
parser.rkt
Normal file
|
@ -0,0 +1,17 @@
|
|||
#lang brag
|
||||
u-program: [/NEWLINE+] (u-expr [/NEWLINE+])*
|
||||
u-expr:
|
||||
u-series ; string series
|
||||
| u-atom
|
||||
| u-converting-num
|
||||
| u-sexp
|
||||
u-sexp:
|
||||
L_PAREN u-expr (SEPERATOR u-expr)* R_PAREN
|
||||
| L_PAREN u-expr (G_SEPERATOR [(/" "|/NEWLINE)+] u-expr [(/" "|/NEWLINE)+])* R_PAREN
|
||||
u-series: (u-atom | u-sexp)+
|
||||
u-converting-num: NUM_CONVERTER (u-id | u-number)
|
||||
u-atom: u-id | u-string | u-number | NEWLINE+
|
||||
u-number: INTEGER | DECIMAL
|
||||
u-id: ID
|
||||
u-string: u-char+
|
||||
u-char: CHAR
|
|
@ -1,7 +1,8 @@
|
|||
#lang uahgi2
|
||||
{@set|@paperwidth|2100}
|
||||
{@set|@paperheight|2970}
|
||||
{@set|@textsize|12}
|
||||
{@set|@paperwidth|`2100}
|
||||
{@set|@paperheight|`2970}
|
||||
{@set|@textsize|`12.3}
|
||||
{@maintext@@
|
||||
{@hd2|測試}
|
||||
他對這塊土地有著愛惜的情感。今天是@today星期@dayofweek。
|
||||
@@}
|
10
scribblings/uahgi2.scrbl
Normal file
10
scribblings/uahgi2.scrbl
Normal file
|
@ -0,0 +1,10 @@
|
|||
#lang scribble/manual
|
||||
@require[@for-label[uahgi2
|
||||
racket/base]]
|
||||
|
||||
@title{uahgi2}
|
||||
@author{chenjt30}
|
||||
|
||||
@defmodule[uahgi2]
|
||||
|
||||
Package Description Here
|
10
tokenizer.rkt
Normal file
10
tokenizer.rkt
Normal file
|
@ -0,0 +1,10 @@
|
|||
#lang br
|
||||
(require "lexer.rkt" brag/support)
|
||||
|
||||
(define (make-tokenizer ip [path #f])
|
||||
(port-count-lines! ip)
|
||||
(lexer-file-path path)
|
||||
(define (next-token) (uahgi2-lexer ip))
|
||||
next-token)
|
||||
|
||||
(provide make-tokenizer)
|
122
unsafe/libharfbuzz.rkt
Normal file
122
unsafe/libharfbuzz.rkt
Normal file
|
@ -0,0 +1,122 @@
|
|||
#lang racket/base
|
||||
|
||||
(require ffi/unsafe)
|
||||
|
||||
; don't use the complete lib. It will crash.
|
||||
(define libhb (ffi-lib "../3rdparty/libharfbuzz-subset"))
|
||||
|
||||
(define-cpointer-type _hb_face_t)
|
||||
(define-cpointer-type _hb_font_t)
|
||||
|
||||
(define-cstruct _hb_glyph_info_t
|
||||
([codepoint _uint32] ;_hb_codepoint_t=_uint32_t
|
||||
[mask _uint32] ; priv. var.
|
||||
[cluster _uint32]
|
||||
[var1 _uint32] ; priv. var.
|
||||
[var2 _uint32] ; priv. var.
|
||||
))
|
||||
|
||||
(define-cstruct _hb_glyph_position_t
|
||||
([x_advance _int32] ;_hb_position_t=_int32_t
|
||||
[y_advance _int32]
|
||||
[x_offset _int32]
|
||||
[y_offset _int32]
|
||||
[var _int32] ; priv. var.
|
||||
))
|
||||
|
||||
|
||||
;hb_buffer_t *
|
||||
;hb_buffer_create (void);
|
||||
(define hb-buffer-create-raw
|
||||
(get-ffi-obj "hb_buffer_create" libhb
|
||||
(_fun -> _pointer)))
|
||||
|
||||
;void
|
||||
;hb_buffer_add_utf8 (hb_buffer_t *buffer,
|
||||
; const char *text,
|
||||
; int text_length,
|
||||
; unsigned int item_offset,
|
||||
; int item_length);
|
||||
(define hb-buffer-add-utf8-raw
|
||||
(get-ffi-obj "hb_buffer_add_utf8" libhb
|
||||
(_fun _pointer _string/utf-8 _int _uint _int -> _void)))
|
||||
|
||||
; not implemented for now. maybe implemented in the future.
|
||||
; // If you know the direction, script, and language
|
||||
; hb_buffer_set_direction(buf, HB_DIRECTION_LTR)
|
||||
; hb_buffer_set_script(buf, HB_SCRIPT_LATIN);
|
||||
; hb_buffer_set_language(buf, hb_language_from_string("en", -1));
|
||||
|
||||
;hb_blob_t *
|
||||
;hb_blob_create_from_file (const char *file_name);
|
||||
(define hb-blob-create-from-file-raw
|
||||
(get-ffi-obj "hb_blob_create_from_file" libhb
|
||||
(_fun _string/utf-8 -> _pointer)))
|
||||
|
||||
;hb_face_t *
|
||||
;hb_face_create (hb_blob_t *blob,
|
||||
; unsigned int index);
|
||||
(define hb-face-create-raw
|
||||
(get-ffi-obj "hb_face_create" libhb
|
||||
(_fun _pointer _uint -> _hb_face_t)))
|
||||
; hb_font_t *
|
||||
; hb_font_create (hb_face_t *face);
|
||||
(define hb-font-create-raw
|
||||
(get-ffi-obj "hb_font_create" libhb
|
||||
(_fun _hb_face_t -> _hb_font_t)))
|
||||
;void
|
||||
;hb_shape (hb_font_t *font,
|
||||
; hb_buffer_t *buffer,
|
||||
; const hb_feature_t *features,
|
||||
; unsigned int num_features);
|
||||
(define hb-shape-raw
|
||||
(get-ffi-obj "hb_shape" libhb
|
||||
(_fun _hb_font_t _pointer _pointer _uint -> _void)))
|
||||
;void
|
||||
;hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
|
||||
(define hb-buffer-guess-segment-properties-raw
|
||||
(get-ffi-obj "hb_buffer_guess_segment_properties" libhb
|
||||
(_fun _pointer -> _void)))
|
||||
|
||||
(define hb-buffer-get-glyph-infos-raw
|
||||
(get-ffi-obj "hb_buffer_get_glyph_infos" libhb
|
||||
(_fun
|
||||
[buf : _pointer]
|
||||
[glyph-length : (_ptr o _uint)]
|
||||
-> [glyph-info : _pointer]
|
||||
-> (values glyph-info glyph-length))))
|
||||
|
||||
(define hb-buffer-get-glyph-positions-raw
|
||||
(get-ffi-obj "hb_buffer_get_glyph_positions" libhb
|
||||
(_fun
|
||||
[buf : _pointer]
|
||||
[glyph-length : (_ptr o _uint)]
|
||||
-> [glyph-position : _pointer]
|
||||
-> (values glyph-position glyph-length))))
|
||||
(define hb-buffer-has-positions-raw
|
||||
(get-ffi-obj "hb_buffer_has_positions" libhb
|
||||
(_fun [buf : _pointer] -> _bool)))
|
||||
|
||||
(define (create-hb-buffer) (hb-buffer-create-raw))
|
||||
|
||||
|
||||
; test area
|
||||
(define buf (create-hb-buffer))
|
||||
(hb-buffer-add-utf8-raw buf "123abc" -1 0 -1)
|
||||
(define font-path "/usr/share/fonts/truetype/freefont/FreeSansBold.ttf")
|
||||
(define blob (hb-blob-create-from-file-raw font-path))
|
||||
(define NULL (cast 0 _int64 _pointer))
|
||||
(define face (hb-face-create-raw blob 0))
|
||||
(define font (hb-font-create-raw face))
|
||||
(hb-buffer-guess-segment-properties-raw buf)
|
||||
(hb-shape-raw font buf NULL 0)
|
||||
(define-values (glyph-info glyph-length) (hb-buffer-get-glyph-infos-raw buf))
|
||||
(define-values (glyph-pos glyph-length2) (hb-buffer-get-glyph-positions-raw buf))
|
||||
|
||||
(printf "has pos ?: ~a" (hb-buffer-has-positions-raw buf))
|
||||
|
||||
|
||||
(for ([i glyph-length])
|
||||
(displayln (hb_glyph_info_t-cluster (ptr-ref glyph-info _hb_glyph_info_t i))))
|
||||
(for ([i glyph-length2])
|
||||
(displayln (hb_glyph_position_t-x_advance (ptr-ref glyph-pos _hb_glyph_position_t i))))
|
BIN
unsafe/libharfbuzz.rkt-autorec.libharfbuzz
Normal file
BIN
unsafe/libharfbuzz.rkt-autorec.libharfbuzz
Normal file
Binary file not shown.
83
unsafe/libharu.rkt
Normal file
83
unsafe/libharu.rkt
Normal file
|
@ -0,0 +1,83 @@
|
|||
#lang racket/base
|
||||
|
||||
(require ffi/unsafe)
|
||||
|
||||
(define libhpdf (ffi-lib "../3rdparty/libhpdf"))
|
||||
|
||||
(define pdf-new-raw
|
||||
(get-ffi-obj "HPDF_New" libhpdf
|
||||
(_fun _int _int -> _pointer)))
|
||||
|
||||
(define pdf-save-raw
|
||||
(get-ffi-obj "HPDF_SaveToFile" libhpdf
|
||||
(_fun _pointer _string/utf-8 -> _int)))
|
||||
|
||||
(define pdf-free-raw
|
||||
(get-ffi-obj "HPDF_Free" libhpdf
|
||||
(_fun _pointer -> _void)))
|
||||
|
||||
(define add-page-raw
|
||||
(get-ffi-obj "HPDF_AddPage" libhpdf
|
||||
(_fun _pointer -> _pointer)))
|
||||
|
||||
(define load-ttf-raw
|
||||
(get-ffi-obj "HPDF_LoadTTFontFromFile" libhpdf
|
||||
(_fun _pointer _string/utf-8 _bool -> _string)))
|
||||
|
||||
(define use-utf-encodingd-raw
|
||||
(get-ffi-obj "HPDF_UseUTFEncodings" libhpdf
|
||||
(_fun _pointer -> _int)))
|
||||
|
||||
(define set-current-encoder-raw
|
||||
(get-ffi-obj "HPDF_SetCurrentEncoder" libhpdf
|
||||
(_fun _pointer _string -> _pointer)))
|
||||
|
||||
(define get-font-raw
|
||||
(get-ffi-obj "HPDF_GetFont" libhpdf
|
||||
(_fun _pointer _string _string/utf-8 -> _pointer)))
|
||||
|
||||
(define set-font-size-raw
|
||||
(get-ffi-obj "HPDF_Page_SetFontAndSize" libhpdf
|
||||
(_fun _pointer _pointer _float -> _pointer)))
|
||||
|
||||
(define page-begin-text-raw
|
||||
(get-ffi-obj "HPDF_Page_BeginText" libhpdf
|
||||
(_fun _pointer -> _pointer)))
|
||||
|
||||
(define page-text-out-raw
|
||||
(get-ffi-obj "HPDF_Page_TextOut" libhpdf
|
||||
(_fun _pointer _float _float _string/utf-8 -> _pointer)))
|
||||
|
||||
(define page-end-text-raw
|
||||
(get-ffi-obj "HPDF_Page_EndText" libhpdf
|
||||
(_fun _pointer -> _pointer)))
|
||||
|
||||
|
||||
(define (new-pdf) (pdf-new-raw 0 0))
|
||||
(define (save-pdf pdf path) (pdf-save-raw pdf path))
|
||||
(define (new-page pdf) (add-page-raw pdf))
|
||||
(define (free-pdf p) (pdf-free-raw p)) ; Error invalid memory reference. Some debugging context lost
|
||||
|
||||
(define (new-ttf-font p font)
|
||||
(define ttf-loaded (load-ttf-raw p font #t))
|
||||
(get-font-raw p ttf-loaded "UTF-8"))
|
||||
(define (use-utf8 p)
|
||||
(use-utf-encodingd-raw p)
|
||||
(set-current-encoder-raw p "UTF-8"))
|
||||
|
||||
(define (set-font-size page font size) (set-font-size-raw page font size))
|
||||
(define (put-text page x y text)
|
||||
(page-begin-text-raw page)
|
||||
(page-text-out-raw page x y text)
|
||||
(page-end-text-raw page)
|
||||
)
|
||||
|
||||
; 以下是測試區
|
||||
(define doc (new-pdf))
|
||||
(define pg (new-page doc))
|
||||
(use-utf8 doc)
|
||||
(define ian-sui (new-ttf-font doc "/home/yoxem/.local/share/fonts/Iansui-Regular.ttf"))
|
||||
(set-font-size pg ian-sui 15.0)
|
||||
(put-text pg 140.0 150.0 "天地人123abc")
|
||||
(save-pdf doc "/tmp/a.pdf")
|
||||
(free-pdf doc)
|
Loading…
Reference in a new issue