From 9636baae38dd0922c5aebe428e5dc2580a692d16 Mon Sep 17 00:00:00 2001 From: anthony Date: Sun, 22 Nov 2020 14:54:45 +0000 Subject: [PATCH] Pull in font.m and plot methods from cocoa port --- frontends/gnustep/BrowserWindowController.m | 36 ++- frontends/gnustep/Makefile | 2 +- frontends/gnustep/PlotView.m | 54 +++- .../gnustep/res/Browser.gorm/objects.gorm | Bin 3060 -> 3060 bytes frontends/gnustep/tables/font.h | 28 ++ frontends/gnustep/tables/font.m | 259 ++++++++++++++++++ frontends/gnustep/tables/layout.m | 44 --- 7 files changed, 366 insertions(+), 57 deletions(-) create mode 100644 frontends/gnustep/tables/font.h create mode 100644 frontends/gnustep/tables/font.m delete mode 100644 frontends/gnustep/tables/layout.m diff --git a/frontends/gnustep/BrowserWindowController.m b/frontends/gnustep/BrowserWindowController.m index ecccd985d..253b179b8 100644 --- a/frontends/gnustep/BrowserWindowController.m +++ b/frontends/gnustep/BrowserWindowController.m @@ -16,7 +16,7 @@ } -(void)awakeFromNib { - plotView = [[PlotView alloc] initWithFrame: NSMakeRect(0, 0, 1000, 1000)]; + plotView = [[PlotView alloc] initWithFrame: NSMakeRect(0, 0, 800, 600)]; [plotView setBrowser: browser]; [[scrollView contentView] addSubview: plotView]; NSLog(@"Browser window loaded"); @@ -24,16 +24,7 @@ -(id)back: (id)sender { NSLog(@"Browser backward"); - [plotView display]; - bool ready = browser_window_redraw_ready(browser); - if (ready) { - NSLog(@"redraw ready!"); - } - if (browser_window_has_content(browser)) { - NSLog(@"has content"); - } - struct nsurl *url = browser_window_access_url(browser); - NSLog(@"url: '%s'", nsurl_access(url)); + } @@ -51,4 +42,27 @@ [plotView setNeedsDisplayInRect: rect]; } +-(BOOL)control: (NSControl*)control textShouldEndEditing: (NSText*)fieldEditor { + NSLog(@"textShouldEndEditing"); + + + nserror error; + struct nsurl *url; + NSString *string = [fieldEditor text]; + error = nsurl_create([string cString], &url); + if (error != NSERROR_OK) { + NSLog(@"nsurl_create error"); + return YES; + } + error = browser_window_navigate(browser, url, NULL, BW_NAVIGATE_HISTORY, NULL, NULL, + NULL); + if (error != NSERROR_OK) { + NSLog(@"browser_window_navigate error"); + } else { + NSLog(@"OK"); + } + nsurl_unref(url); + return YES; +} + @end diff --git a/frontends/gnustep/Makefile b/frontends/gnustep/Makefile index c4ca9b7ee..80b916d04 100644 --- a/frontends/gnustep/Makefile +++ b/frontends/gnustep/Makefile @@ -47,9 +47,9 @@ S_FRONTEND := \ tables/clipboard.m \ tables/download.m \ tables/fetch.m \ - tables/layout.m \ tables/search.m \ tables/window.m \ + tables/font.m \ # This is the final source build list diff --git a/frontends/gnustep/PlotView.m b/frontends/gnustep/PlotView.m index 6103fd261..55d595f25 100644 --- a/frontends/gnustep/PlotView.m +++ b/frontends/gnustep/PlotView.m @@ -94,22 +94,56 @@ void cocoa_plot_render_path(NSBezierPath *path, const plot_style_t *pstyle) static nserror plot_clip(const struct redraw_context *ctx, const struct rect *clip) { NSLog(@"plot_clip"); cocoa_plot_clip_rect = NSMakeRect(clip->x0, clip->y0, clip->x1, clip->y1); - //[NSBezierPath clipRect: ]; return NSERROR_OK; } static nserror plot_arc(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int y, int radius, int angle1, int angle2) { NSLog(@"plot_arc"); + NSBezierPath *path = [NSBezierPath bezierPath]; + [path appendBezierPathWithArcWithCenter: NSMakePoint( x, y ) radius: radius + startAngle: angle1 endAngle: angle2 clockwise: NO]; + + cocoa_plot_render_path(path, pstyle); + return NSERROR_OK; } static nserror plot_disc(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int y, int radius) { NSLog(@"plot_disc"); + NSBezierPath *path = [NSBezierPath bezierPathWithOvalInRect: + NSMakeRect( x - radius, y-radius, 2*radius, 2*radius )]; + + cocoa_plot_render_path( path, pstyle ); + return NSERROR_OK; } static nserror plot_line(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *line) { NSLog(@"plot_line"); + int x0 = line->x0; + int y0 = line->y0; + int x1 = line->x1; + int y1 = line->y1; + + if (pstyle->stroke_type == PLOT_OP_TYPE_NONE) return NSERROR_OK; + + [NSGraphicsContext saveGraphicsState]; + [NSBezierPath clipRect: cocoa_plot_clip_rect]; + + NSBezierPath *path = [NSBezierPath bezierPath]; + [path moveToPoint: NSMakePoint( x0, y0 )]; + [path lineToPoint: NSMakePoint( x1, y1 )]; + cocoa_plot_path_set_stroke_pattern( path, pstyle ); + + const bool horizontal = y0 == y1; + const bool vertical = x0 == x1; + const bool oddThickness = pstyle->stroke_width != 0 ? (pstyle->stroke_width % 2) != 0 : true; + + [cocoa_convert_colour( pstyle->stroke_colour ) set]; + [path stroke]; + + [NSGraphicsContext restoreGraphicsState]; + return NSERROR_OK; } @@ -125,6 +159,17 @@ static nserror plot_rectangle(const struct redraw_context *ctx, const plot_style static nserror plot_polygon(const struct redraw_context *ctx, const plot_style_t *pstyle, const int *p, unsigned int n) { NSLog(@"plot_polygon"); + if (n <= 1) return NSERROR_OK; + + NSBezierPath *path = [NSBezierPath bezierPath]; + [path moveToPoint: NSMakePoint(p[0], p[1])]; + for (unsigned int i = 1; i < n; i++) { + [path lineToPoint: NSMakePoint(p[2*i], p[2*i+1])]; + } + [path closePath]; + + cocoa_plot_render_path( path, pstyle ); + return NSERROR_OK; } @@ -140,6 +185,13 @@ static nserror plot_bitmap(const struct redraw_context *ctx, struct bitmap *bitm static nserror plot_text(const struct redraw_context *ctx, const plot_font_style_t *fstyle, int x, int y, const char *text, size_t length) { NSLog(@"plot_text"); + [NSGraphicsContext saveGraphicsState]; + [NSBezierPath clipRect: cocoa_plot_clip_rect]; + + cocoa_draw_string(x, y, text, length, fstyle); + + [NSGraphicsContext restoreGraphicsState]; + return NSERROR_OK; } diff --git a/frontends/gnustep/res/Browser.gorm/objects.gorm b/frontends/gnustep/res/Browser.gorm/objects.gorm index dc30ad1eb3b8f77f6d238b05032b62c186c6f308..2983f858b30638c44ca0971125f79317f1fc9510 100644 GIT binary patch delta 354 zcmX|-%}T>i5QTFS+uY<91*?`?DE-Mzn%3&1h1Nf;#46%S@Cn?DLTUG1cNG}WwQDyM z0^$oO?tB9gaU+7OK7cnHH)lT1FvFag7v=@(GxJr`#Bgzn2ke*GNn8J7T+>-Y)3jVt zTmZ&$$ysK=*m5$bz8R1|9t1 z5=-{Up%+0fUZ*ZqBIqkfoZQ-#{JQ1gCxgFACmp{~v$u4*oaK&a>1N$@huo4pJKKi*KRLTKcDuLKlI?HOrYG z*gQ-0VwqZffsR}j9{RE@>Ub&}B|l2mdDQl}B^G1S`{U8*<~o3o(h%TFvM55llV!Y> zD`q>SC47_>lS*XZo2*zoW4tcW{pBON-sHWg3Dv(DtJaK!5PaaO) Pq7kq@xK;kytLyy$K)h$J diff --git a/frontends/gnustep/tables/font.h b/frontends/gnustep/tables/font.h new file mode 100644 index 000000000..ed0479765 --- /dev/null +++ b/frontends/gnustep/tables/font.h @@ -0,0 +1,28 @@ +/* + * Copyright 2011 Sven Weidauer + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef COCOA_FONT_H +#define COCOA_FONT_H + +#import "netsurf/plot_style.h" + +void cocoa_draw_string( CGFloat x, CGFloat y, const char *bytes, size_t length, const struct plot_font_style *style ); + +struct gui_layout_table *cocoa_layout_table; + +#endif diff --git a/frontends/gnustep/tables/font.m b/frontends/gnustep/tables/font.m new file mode 100644 index 000000000..bf5f9d79e --- /dev/null +++ b/frontends/gnustep/tables/font.m @@ -0,0 +1,259 @@ +/* + * Copyright 2011 Sven Weidauer + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import +#import +#import + +#import "utils/nsoption.h" +#import "netsurf/layout.h" +#import "netsurf/plotters.h" + +#import "font.h" + + +#define colour_red_component( c ) (((c) >> 0) & 0xFF) +#define colour_green_component( c ) (((c) >> 8) & 0xFF) +#define colour_blue_component( c ) (((c) >> 16) & 0xFF) +#define colour_alpha_component( c ) (((c) >> 24) & 0xFF) +#define colour_from_rgba( r, g, b, a) ((((colour)(r)) << 0) | \ + (((colour)(g)) << 8) | \ + (((colour)(b)) << 16) | \ + (((colour)(a)) << 24)) +#define colour_from_rgb( r, g, b ) colour_from_rgba( (r), (g), (b), 0xFF ) + +NSColor *cocoa_convert_colour( colour clr ) +{ + return [NSColor colorWithDeviceRed: (float)colour_red_component( clr ) / 0xFF + green: (float)colour_green_component( clr ) / 0xFF + blue: (float)colour_blue_component( clr ) / 0xFF + alpha: 1.0]; +} + +static NSLayoutManager *cocoa_prepare_layout_manager( const char *string, size_t length, + const plot_font_style_t *style ); +static CGFloat cocoa_layout_width( NSLayoutManager *layout ); +static CGFloat cocoa_layout_width_chars( NSLayoutManager *layout, size_t characters ); +static NSUInteger cocoa_glyph_for_location( NSLayoutManager *layout, CGFloat x ); +static size_t cocoa_bytes_for_characters( const char *string, size_t characters ); +static NSDictionary *cocoa_font_attributes( const plot_font_style_t *style ); + +static NSTextStorage *cocoa_text_storage = nil; +static NSTextContainer *cocoa_text_container = nil; + +static nserror cocoa_font_width(const plot_font_style_t *style, + const char *string, size_t length, + int *width) +{ + NSLayoutManager *layout; + layout = cocoa_prepare_layout_manager( string, length, style ); + *width = cocoa_layout_width( layout ); + return NSERROR_OK; +} + +static nserror cocoa_font_position(const plot_font_style_t *style, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x) +{ + NSLayoutManager *layout = cocoa_prepare_layout_manager( string, length, style ); + if (layout == nil) { + return NSERROR_BAD_PARAMETER; + } + + NSUInteger glyphIndex = cocoa_glyph_for_location( layout, x ); + NSUInteger chars = [layout characterIndexForGlyphAtIndex: glyphIndex]; + + if (chars >= [cocoa_text_storage length]) *char_offset = length; + else *char_offset = cocoa_bytes_for_characters( string, chars ); + + *actual_x = NSMaxX([layout boundingRectForGlyphRange: NSMakeRange(glyphIndex - 1, 1) + inTextContainer: cocoa_text_container]); + return NSERROR_OK; +} + +static nserror cocoa_font_split(const plot_font_style_t *style, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x) +{ + NSLayoutManager *layout = cocoa_prepare_layout_manager( string, length, style ); + if (layout == nil) return NSERROR_BAD_PARAMETER; + + NSUInteger glyphIndex = cocoa_glyph_for_location( layout, x ); + NSUInteger chars = [layout characterIndexForGlyphAtIndex: glyphIndex]; + + if (chars >= [cocoa_text_storage length]) { + *char_offset = length; + *actual_x = cocoa_layout_width( layout ); + return NSERROR_OK; + } + + + chars = [[cocoa_text_storage string] rangeOfString: @" " options: NSBackwardsSearch range: NSMakeRange( 0, chars + 1 )].location; + if (chars == NSNotFound) { + *char_offset = 0; + *actual_x = 0; + return NSERROR_OK; + } + + *char_offset = cocoa_bytes_for_characters( string, chars ); + *actual_x = cocoa_layout_width_chars( layout, chars ); + + return NSERROR_OK; +} + + +struct gui_layout_table gnustep_layout_table = { + .width = cocoa_font_width, + .position = cocoa_font_position, + .split = cocoa_font_split, +}; + + +#pragma mark - + +void cocoa_draw_string( CGFloat x, CGFloat y, const char *bytes, size_t length, const plot_font_style_t *style ) +{ + NSLayoutManager *layout = cocoa_prepare_layout_manager( bytes, length, style ); + if (layout == nil) return; + + NSFont *font = [cocoa_text_storage attribute: NSFontAttributeName atIndex: 0 effectiveRange: NULL]; + + CGFloat baseline = [font defaultLineHeightForFont] * 3.0 / 4.0; + + NSRange glyphRange = [layout glyphRangeForTextContainer: cocoa_text_container]; + [layout drawGlyphsForGlyphRange: glyphRange atPoint: NSMakePoint( x, y - baseline )]; +} + + +#pragma mark - + +static inline CGFloat cocoa_layout_width( NSLayoutManager *layout ) +{ + if (layout == nil) return 0.0; + + return NSWidth([layout usedRectForTextContainer: cocoa_text_container]); +} + +static inline CGFloat cocoa_layout_width_chars( NSLayoutManager *layout, size_t characters ) +{ + NSUInteger glyphIndex = [layout glyphIndexForCharacterAtIndex: characters]; + return [layout locationForGlyphAtIndex: glyphIndex].x; +} + +static inline NSUInteger cocoa_glyph_for_location( NSLayoutManager *layout, CGFloat x ) +{ + CGFloat fraction = 0.0; + NSUInteger glyphIndex = [layout glyphIndexForPoint: NSMakePoint(x, 0 ) + inTextContainer: cocoa_text_container + fractionOfDistanceThroughGlyph: &fraction]; + if (fraction >= 1.0) ++glyphIndex; + return glyphIndex; +} + +static inline size_t cocoa_bytes_for_characters( const char *string, size_t chars ) +{ + size_t offset = 0; + while (chars-- > 0) { + uint8_t ch = ((uint8_t *)string)[offset]; + + if (0xC2 <= ch && ch <= 0xDF) offset += 2; + else if (0xE0 <= ch && ch <= 0xEF) offset += 3; + else if (0xF0 <= ch && ch <= 0xF4) offset += 4; + else offset++; + } + return offset; +} + +static NSLayoutManager *cocoa_prepare_layout_manager( const char *bytes, size_t length, + const plot_font_style_t *style ) +{ + if (NULL == bytes || 0 == length) return nil; + + NSString *string = [[[NSString alloc] initWithBytes: bytes length:length encoding:NSUTF8StringEncoding] autorelease]; + if (string == nil) return nil; + + static NSLayoutManager *layout = nil; + if (nil == layout) { + cocoa_text_container = [[NSTextContainer alloc] initWithContainerSize: NSMakeSize( CGFLOAT_MAX, CGFLOAT_MAX )]; + [cocoa_text_container setLineFragmentPadding: 0]; + + layout = [[NSLayoutManager alloc] init]; + [layout addTextContainer: cocoa_text_container]; + } + + static NSString *oldString = 0; + static plot_font_style_t oldStyle = { 0, 0, 0, 0, 0, 0 }; + + const bool styleChanged = memcmp( style, &oldStyle, sizeof oldStyle ) != 0; + + if ([oldString isEqualToString: string] && !styleChanged) { + return layout; + } + + [oldString release]; + oldString = [string copy]; + oldStyle = *style; + + static NSDictionary *attributes = nil; + if (styleChanged || attributes == nil) { + [attributes release]; + attributes = [cocoa_font_attributes( style ) retain]; + } + + [cocoa_text_storage release]; + cocoa_text_storage = [[NSTextStorage alloc] initWithString: string attributes: attributes]; + [cocoa_text_storage addLayoutManager: layout]; + + [layout ensureLayoutForTextContainer: cocoa_text_container]; + + return layout; +} + +static NSString * const cocoa_font_families[PLOT_FONT_FAMILY_COUNT] = { + [PLOT_FONT_FAMILY_SERIF] = @"Times", + [PLOT_FONT_FAMILY_SANS_SERIF] = @"Helvetica", + [PLOT_FONT_FAMILY_MONOSPACE] = @"Courier", + [PLOT_FONT_FAMILY_CURSIVE] = @"Apple Chancery", + [PLOT_FONT_FAMILY_FANTASY] = @"Marker Felt" +}; + +static inline NSFont *cocoa_font_get_nsfont( const plot_font_style_t *style ) +{ + NSFont *font = [NSFont fontWithName: cocoa_font_families[style->family] + size: (CGFloat)style->size / PLOT_STYLE_SCALE]; + + NSFontTraitMask traits = 0; + if (style->flags & FONTF_ITALIC || style->flags & FONTF_OBLIQUE) traits |= NSItalicFontMask; + if (style->flags & FONTF_SMALLCAPS) traits |= NSSmallCapsFontMask; + if (style->weight > 400) traits |= NSBoldFontMask; + + if (0 != traits) { + NSFontManager *fm = [NSFontManager sharedFontManager]; + font = [fm convertFont: font toHaveTrait: traits]; + } + + return font; +} + +static inline NSDictionary *cocoa_font_attributes( const plot_font_style_t *style ) +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + cocoa_font_get_nsfont( style ), NSFontAttributeName, + cocoa_convert_colour( style->foreground ), NSForegroundColorAttributeName, + nil]; +} diff --git a/frontends/gnustep/tables/layout.m b/frontends/gnustep/tables/layout.m deleted file mode 100644 index 128582def..000000000 --- a/frontends/gnustep/tables/layout.m +++ /dev/null @@ -1,44 +0,0 @@ -#import -#import - -#import "netsurf/netsurf.h" -#import "netsurf/layout.h" - - - -/********************/ -/****** Layout ******/ -/********************/ - -// Put the measured width of the string into width -static nserror gnustep_layout_width(const struct plot_font_style *fstyle, const char *string, size_t length, int *width) { - NSLog(@"gnustep_layout_width of %s, len %d", string, length); - if (string == NULL || length == 0) { - *width = 0; - return NSERROR_OK; - } - // TODO: = impl properly. - *width = 5 * length; - return NSERROR_OK; -} - -// Put the character offset and actual x coordinate of the character for which the x -// coordinate is nearest to -static nserror gnustep_layout_position(const struct plot_font_style *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { - *char_offset = 0; - *actual_x = 0; - NSLog(@"gnustep_layout_position"); -} - -// Put the char offset and x coordinate of where to split a string so it fits in width x -static nserror gnustep_layout_split(const struct plot_font_style *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { - *char_offset = 0; - *actual_x = 0; - NSLog(@"gnustep_layout_split"); -} - -struct gui_layout_table gnustep_layout_table = { - .width = gnustep_layout_width, - .position = gnustep_layout_position, - .split = gnustep_layout_split -}; \ No newline at end of file