1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

gg: native rendering mode on macOS

This commit is contained in:
Alexander Medvednikov
2021-01-23 10:25:40 +01:00
parent a3908414e4
commit d991712b3c
32 changed files with 492 additions and 152 deletions

View File

@@ -40,6 +40,7 @@ pub:
bg_color gx.Color
init_fn FNCb = voidptr(0)
frame_fn FNCb = voidptr(0)
native_frame_fn FNCb = voidptr(0)
cleanup_fn FNCb = voidptr(0)
fail_fn FNFail = voidptr(0)
event_fn FNEvent = voidptr(0)
@@ -65,6 +66,7 @@ pub:
font_bytes_bold []byte
font_bytes_mono []byte
font_bytes_italic []byte
native_rendering bool // Cocoa on macOS/iOS, GDI+ on Windows
}
pub struct Context {
@@ -75,6 +77,8 @@ mut:
image_cache []Image
needs_refresh bool = true
ticks int
pub:
native_rendering bool
pub mut:
scale f32 = 1.0
// will get set to 2.0 for retina, will remain 1.0 for normal
@@ -169,6 +173,9 @@ fn gg_init_sokol_window(user_data voidptr) {
g.config.init_fn(g.config.user_data)
}
// Create images now that we can do that after sg is inited
if g.native_rendering {
return
}
for i in 0 .. g.image_cache.len {
g.image_cache[i].init_sokol_image()
}
@@ -179,6 +186,9 @@ fn gg_frame_fn(user_data voidptr) {
if ctx.config.frame_fn == voidptr(0) {
return
}
if ctx.native_rendering {
// return
}
if ctx.ui_mode && !ctx.needs_refresh {
// Draw 3 more frames after the "stop refresh" command
ctx.ticks++
@@ -256,6 +266,7 @@ pub fn new_context(cfg Config) &Context {
render_text: cfg.font_path != '' || cfg.font_bytes_normal.len > 0
ft: 0
ui_mode: cfg.ui_mode
native_rendering: cfg.native_rendering
}
g.set_bg_color(cfg.bg_color)
// C.printf('new_context() %p\n', cfg.user_data)
@@ -273,6 +284,7 @@ pub fn new_context(cfg Config) &Context {
sample_count: cfg.sample_count
high_dpi: true
fullscreen: cfg.fullscreen
native_render: cfg.native_rendering
}
if cfg.use_ortho {
} else {
@@ -292,6 +304,12 @@ pub fn (mut ctx Context) set_bg_color(c gx.Color) {
// TODO: Fix alpha
pub fn (ctx &Context) draw_rect(x f32, y f32, w f32, h f32, c gx.Color) {
$if macos {
if ctx.native_rendering {
C.darwin_draw_rect(x, ctx.height - (y + h), w, h, c)
return
}
}
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
}
@@ -357,6 +375,12 @@ pub fn (ctx &Context) draw_circle_line(x f32, y f32, r int, segments int, c gx.C
}
pub fn (ctx &Context) draw_circle(x f32, y f32, r f32, c gx.Color) {
$if macos {
if ctx.native_rendering {
C.darwin_draw_circle(x - r + 1, ctx.height - (y + r + 3), r, c)
return
}
}
if ctx.scale == 1 {
ctx.draw_circle_with_segments(x, y, r, 10, c)
} else {

View File

@@ -2,3 +2,19 @@ module gg
#include "@VROOT/vlib/gg/gg_darwin.m"
fn C.gg_get_screen_size() Size
fn C.darwin_draw_string(x int, y int, s string)
fn C.darwin_text_width(s string) int
fn C.darwin_window_refresh()
fn C.darwin_draw_rect(f32, f32, f32, f32)
fn C.darwin_create_image() Image
fn C.darwin_draw_image(f32, f32, f32, f32, &Image)
fn C.darwin_draw_circle(f32, f32, f32)
//, gx.Color c)

View File

@@ -1,5 +1,18 @@
#include <Cocoa/Cocoa.h>
NSColor* nscolor(gx__Color c) {
float red= (float)c.r / 255.0f;
float green= (float)c.g / 255.0f;
float blue= (float)c.b / 255.0f;
return [NSColor colorWithDeviceRed:red green:green blue:blue alpha:1.0f];
}
NSString* nsstring(string s) {
return [ [ NSString alloc ] initWithBytesNoCopy:s.str length:s.len
encoding:NSUTF8StringEncoding freeWhenDone: false];
}
gg__Size gg_get_screen_size() {
NSScreen *screen = [NSScreen mainScreen];
NSDictionary *description = [screen deviceDescription];
@@ -12,3 +25,101 @@ gg__Size gg_get_screen_size() {
return res;
}
void darwin_draw_string(int x, int y, string s, gx__TextCfg cfg) {
NSFont* font = [NSFont userFontOfSize: 0]; //cfg.size];
// # NSFont* font = [NSFont fontWithName:@"Roboto Mono" size:cfg.size];
if (cfg.mono) {
// # font = [NSFont fontWithName:@"Roboto Mono" size:cfg.size];
font = [NSFont fontWithName:@"Menlo" size:cfg.size-5];
}
if (cfg.bold) {
font = [[NSFontManager sharedFontManager] convertFont:font toHaveTrait:NSBoldFontMask];
}
NSDictionary* attr = @{
NSForegroundColorAttributeName: nscolor(cfg.color),
//NSParagraphStyleAttributeName: paragraphStyle,
NSFontAttributeName: font,
};
[nsstring(s) drawAtPoint:NSMakePoint(x,y-15) withAttributes:attr];
}
int darwin_text_width(string s) {
// println('text_width "$s" len=$s.len')
NSString* n = @"";
if (s.len == 1) {
// println('len=1')
n=[NSString stringWithFormat:@"%c" , s.str[0]];
}
else {
n = nsstring(s);
}
/*
# if (!defaultFont){
# defaultFont = [NSFont userFontOfSize: ui__DEFAULT_FONT_SIZE];
# }
# NSDictionary *attrs = @{
# NSFontAttributeName: defaultFont,
# };
*/
NSSize size = [n sizeWithAttributes:nil];
// # printf("!!!%f\n", ceil(size.width));
return (int)(ceil(size.width));
}
void darwin_draw_rect(float x, float y, float width, float height, gx__Color c) {
NSColor* color = nscolor(c);
NSRect rect = NSMakeRect(x, y, width, height);
[color setFill];
NSRectFill(rect);
}
void darwin_window_refresh() {
//[g_view setNeedsDisplay:YES];
// update UI on the main thread TODO separate fn
dispatch_async(dispatch_get_main_queue(), ^{
[g_view setNeedsDisplay:YES];
});
//puts("refresh");
//[g_view drawRect:NSMakeRect(0,0,2000,2000)];
//[[NSGraphicsContext currentContext] flushGraphics];
}
gg__Image darwin_create_image(string path_) {
// file = file.trim_space()
NSString* path = nsstring(path_);
NSImage* img = [[NSImage alloc] initWithContentsOfFile:path];
if (img == 0) {
}
NSSize size = [img size];
gg__Image res;
res.width = size.width;
res.height = size.height;
res.path = path_;
res.ok = true;
//printf("inited img width=%d\n", res.width) ;
// need __brige_retained so that the pointer is not freed by ARC
res.data = (__bridge_retained voidptr)(img);
return res;
}
void darwin_draw_image(float x, float y, float w, float h, gg__Image* img) {
NSImage* i= (__bridge NSImage*)(img->data);
[i drawInRect:NSMakeRect(x,y,w,h)];
}
void darwin_draw_circle(float x, float y, float d, gx__Color color) {
NSColor* c = nscolor(color);
NSRect rect = NSMakeRect(x, y, d * 2, d * 2);
NSBezierPath* circlePath = [NSBezierPath bezierPath];
[circlePath appendBezierPathWithOvalInRect: rect];
[c setFill];
// [circlePath stroke];
[circlePath fill];
// NSRectFill(rect);
}

View File

@@ -28,6 +28,21 @@ fn C.sg_isvalid() bool
// TODO return ?Image
pub fn (mut ctx Context) create_image(file string) Image {
// println('\ncreate_image("$file")')
if !os.exists(file) {
return Image{}
}
$if macos {
if ctx.native_rendering {
// return C.darwin_create_image(file)
mut img := C.darwin_create_image(file)
// println('created macos image: $img.path w=$img.width')
// C.printf('p = %p\n', img.data)
img.id = ctx.image_cache.len
ctx.image_cache << img
return img
}
}
if !C.sg_isvalid() {
// Sokol is not initialized yet, add stbi object to a queue/cache
// ctx.image_queue << file
@@ -142,6 +157,18 @@ pub fn (ctx &Context) draw_image(x f32, y f32, width f32, height f32, img_ &Imag
return
}
img := ctx.image_cache[img_.id] // fetch the image from cache
$if macos {
if ctx.native_rendering {
if img_.width == 0 {
return
}
if !os.exists(img_.path) {
return
}
C.darwin_draw_image(x, ctx.height - (y + height), width, height, img_)
return
}
}
if !img.simg_ok {
return
}

View File

@@ -35,6 +35,13 @@ struct FTConfig {
bytes_italic []byte
}
struct StringToRender {
x int
y int
text string
cfg gx.TextCfg
}
fn new_ft(c FTConfig) ?&FT {
if c.font_path == '' {
if c.bytes_normal.len > 0 {
@@ -150,6 +157,17 @@ fn (ctx &Context) set_cfg(cfg gx.TextCfg) {
}
pub fn (ctx &Context) draw_text(x int, y int, text_ string, cfg gx.TextCfg) {
$if macos {
if ctx.native_rendering {
if cfg.align == gx.align_right {
width := ctx.text_width(text_)
C.darwin_draw_string(x - width, ctx.height - y, text_, cfg)
} else {
C.darwin_draw_string(x, ctx.height - y, text_, cfg)
}
return
}
}
if !ctx.font_inited {
eprintln('gg: draw_text(): font not initialized')
return
@@ -177,6 +195,11 @@ pub fn (ft &FT) flush() {
}
pub fn (ctx &Context) text_width(s string) int {
$if macos {
if ctx.native_rendering {
return C.darwin_text_width(s)
}
}
// ctx.set_cfg(cfg) TODO
if !ctx.font_inited {
return 0
@@ -187,6 +210,13 @@ pub fn (ctx &Context) text_width(s string) int {
return int((buf[2] - buf[0]) / ctx.scale) +
ctx.text_width('i') // TODO fix this in fontstash?
}
res := int((buf[2] - buf[0]) / ctx.scale)
// println('TW "$s" = $res')
$if macos {
if ctx.native_rendering {
return res * 2
}
}
return int((buf[2] - buf[0]) / ctx.scale)
}