summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/debugger
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2015-02-14 09:04:39 +1100
committer Vas Crabb <vas@vastheman.com>2015-02-14 18:00:56 +1100
commit146653f9d701fe7c5acc8a2b66df06c08fd98c23 (patch)
treea0722a655cf7c6b5b8823a5aef0adb6c1020248c /src/osd/modules/debugger
parentb8a7b454d2e78a326bad22bf9678e2dab9983e9b (diff)
Far better handling of font metrics in Cocoa debugger, and more efficient drawing
Diffstat (limited to 'src/osd/modules/debugger')
-rw-r--r--src/osd/modules/debugger/osx/debugosxdebugview.h4
-rw-r--r--src/osd/modules/debugger/osx/debugosxdebugview.m196
-rw-r--r--src/osd/modules/debugger/osx/debugosxdisassemblyview.m1
-rw-r--r--src/osd/modules/debugger/osx/debugosxmemoryview.m1
4 files changed, 132 insertions, 70 deletions
diff --git a/src/osd/modules/debugger/osx/debugosxdebugview.h b/src/osd/modules/debugger/osx/debugosxdebugview.h
index d87ecdb3015..9688fa48b8e 100644
--- a/src/osd/modules/debugger/osx/debugosxdebugview.h
+++ b/src/osd/modules/debugger/osx/debugosxdebugview.h
@@ -45,6 +45,10 @@
NSFont *font;
CGFloat fontWidth, fontHeight, fontAscent;
+
+ NSTextStorage *text;
+ NSTextContainer *textContainer;
+ NSLayoutManager *layoutManager;
}
+ (NSFont *)defaultFont;
diff --git a/src/osd/modules/debugger/osx/debugosxdebugview.m b/src/osd/modules/debugger/osx/debugosxdebugview.m
index d893bb0ad2f..a0755650613 100644
--- a/src/osd/modules/debugger/osx/debugosxdebugview.m
+++ b/src/osd/modules/debugger/osx/debugosxdebugview.m
@@ -58,16 +58,64 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
- (debug_view_xy)convertLocation:(NSPoint)location {
debug_view_xy position;
- position.x = lround(floor(location.x / fontWidth));
+
position.y = lround(floor(location.y / fontHeight));
- if (position.x < 0)
- position.x = 0;
- else if (position.x >= totalWidth)
- position.x = totalWidth - 1;
if (position.y < 0)
position.y = 0;
else if (position.y >= totalHeight)
position.y = totalHeight - 1;
+
+ debug_view_xy const origin = view->visible_position();
+ debug_view_xy const size = view->visible_size();
+ debug_view_char const *data = view->viewdata();
+ if (!data || (position.y < origin.y) || (position.y >= origin.y + size.y))
+ {
+ // y coordinate outside visible area, x will be a guess
+ position.x = lround(floor(location.x / fontWidth));
+ }
+ else
+ {
+ data += ((position.y - view->visible_position().y) * view->visible_size().x);
+ int attr = -1;
+ NSUInteger start = 0, length = 0;
+ for (UINT32 col = origin.x; col < origin.x + size.x; col++)
+ {
+ [[text mutableString] appendFormat:@"%c", data[col - origin.x].byte];
+ if ((start < length) && (attr != data[col - origin.x].attrib))
+ {
+ NSRange const run = NSMakeRange(start, length - start);
+ [text addAttribute:NSFontAttributeName
+ value:font
+ range:NSMakeRange(0, length)];
+ [text addAttribute:NSForegroundColorAttributeName
+ value:[self foregroundForAttribute:attr]
+ range:run];
+ start = length;
+ }
+ attr = data[col - origin.x].attrib;
+ length = [text length];
+ }
+ if (start < length)
+ {
+ NSRange const run = NSMakeRange(start, length - start);
+ [text addAttribute:NSFontAttributeName
+ value:font
+ range:NSMakeRange(0, length)];
+ [text addAttribute:NSForegroundColorAttributeName
+ value:[self foregroundForAttribute:attr]
+ range:run];
+ }
+ CGFloat fraction;
+ NSUInteger const glyph = [layoutManager glyphIndexForPoint:NSMakePoint(location.x, fontHeight / 2)
+ inTextContainer:textContainer
+ fractionOfDistanceThroughGlyph:&fraction];
+ position.x = [layoutManager characterIndexForGlyphAtIndex:glyph]; // FIXME: assumes 1:1 character mapping
+ }
+ if (position.x < 0)
+ position.x = 0;
+ else if (position.x >= totalWidth)
+ position.x = totalWidth - 1;
+
return position;
}
@@ -75,6 +123,8 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
- (void)convertBounds:(NSRect)b toPosition:(debug_view_xy *)origin size:(debug_view_xy *)size {
origin->x = lround(floor(b.origin.x / fontWidth));
origin->y = lround(floor(b.origin.y / fontHeight));
+
+ // FIXME: this is not using proper font metrics horizontally
size->x = lround(ceil((b.origin.x + b.size.width) / fontWidth)) - origin->x;
size->y = lround(ceil((b.origin.y + b.size.height) / fontHeight)) - origin->y;
}
@@ -107,7 +157,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
{
debug_view_xy newPos = view->cursor_position();
if ((newPos.x != oldPos.x) || (newPos.y != oldPos.y)) {
- [self scrollRectToVisible:NSMakeRect(newPos.x * fontWidth,
+ [self scrollRectToVisible:NSMakeRect(newPos.x * fontWidth, // FIXME - use proper metrics
newPos.y * fontHeight,
fontWidth,
fontHeight)];
@@ -120,8 +170,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
+ (NSFont *)defaultFont {
- // maybe we should get the configured system fixed-width font...
- return [NSFont fontWithName:@"Monaco" size:10];
+ return [NSFont userFixedPitchFontOfSize:0];
}
@@ -138,14 +187,21 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
totalWidth = totalHeight = 0;
originLeft = originTop = 0;
[self setFont:[[self class] defaultFont]];
+ text = [[NSTextStorage alloc] init];
+ textContainer = [[NSTextContainer alloc] init];
+ layoutManager = [[NSLayoutManager alloc] init];
+ [layoutManager addTextContainer:textContainer];
+ [text addLayoutManager:layoutManager];
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
- if (font != nil)
- [font release];
+ if (font != nil) [font release];
+ if (text != nil) [text release];
+ if (textContainer != nil) [textContainer release];
+ if (layoutManager != nil) [layoutManager release];
[super dealloc];
}
@@ -156,7 +212,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
// resize our frame if the total size has changed
newSize = view->total_size();
if ((newSize.x != totalWidth) || (newSize.y != totalHeight)) {
- [self setFrameSize:NSMakeSize(fontWidth * newSize.x, fontHeight * newSize.y)];
+ [self setFrameSize:NSMakeSize(fontWidth * newSize.x, fontHeight * newSize.y)]; // FIXME: metrics
totalWidth = newSize.x;
totalHeight = newSize.y;
}
@@ -221,7 +277,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
debug_view_xy pos;
view->set_cursor_visible(true);
pos = view->cursor_position();
- [self scrollRectToVisible:NSMakeRect(pos.x * fontWidth, pos.y * fontHeight, fontWidth, fontHeight)];
+ [self scrollRectToVisible:NSMakeRect(pos.x * fontWidth, pos.y * fontHeight, fontWidth, fontHeight)]; // FIXME: metrics
[self setNeedsDisplay:YES];
return [super becomeFirstResponder];
} else {
@@ -266,73 +322,77 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
- (void)drawRect:(NSRect)dirtyRect {
- const debug_view_char *base;
- debug_view_xy origin, size;
- debug_view_xy position, clip;
- NSMutableString *text;
- NSMutableDictionary *attributes;
- UINT32 pass, row, col;
+ debug_view_xy position, clip;
// work out how much we need to draw
[self recomputeVisible];
- origin = view->visible_position();
- size = view->visible_size();
+ debug_view_xy const origin = view->visible_position();
+ debug_view_xy const size = view->visible_size();
[self convertBounds:dirtyRect toPosition:&position size:&clip];
// this gets the text for the whole visible area
- base = view->viewdata();
- if (!base)
+ debug_view_char const *data = view->viewdata();
+ if (!data)
return;
- text = [[NSMutableString alloc] initWithCapacity:clip.x];
- attributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:font, NSFontAttributeName, nil];
- for (pass = 0; pass < 2; pass++) {
- const debug_view_char *data = base + ((position.y - origin.y) * size.x);
- for (row = position.y; row < position.y + clip.y; row++, data += size.x) {
- int attr = -1;
-
- if ((row < origin.y) || (row >= origin.y + size.y))
- continue;
-
- // render entire lines to get character alignment right
- for (col = origin.x; col < origin.x + size.x; col++) {
- if ((attr != data[col - origin.x].attrib) && ([text length] > 0)) {
- if (pass == 0) {
- [[self backgroundForAttribute:attr] set];
- [NSBezierPath fillRect:NSMakeRect((col - [text length]) * fontWidth,
- row * fontHeight,
- [text length] * fontWidth,
- fontHeight)];
- } else {
- [attributes setObject:[self foregroundForAttribute:attr]
- forKey:NSForegroundColorAttributeName];
- [text drawAtPoint:NSMakePoint((col - [text length]) * fontWidth, row * fontHeight)
- withAttributes:attributes];
- }
- [text setString:@""];
- }
- attr = data[col - origin.x].attrib;
- [text appendFormat:@"%c", data[col - origin.x].byte];
- }
- if ([text length] > 0) {
- if (pass == 0) {
- [[self backgroundForAttribute:attr] set];
- [NSBezierPath fillRect:NSMakeRect((col - [text length]) * fontWidth,
- row * fontHeight,
- [text length] * fontWidth,
- fontHeight)];
- } else {
- [attributes setObject:[self foregroundForAttribute:attr]
- forKey:NSForegroundColorAttributeName];
- [text drawAtPoint:NSMakePoint((col - [text length]) * fontWidth, row * fontHeight)
- withAttributes:attributes];
- }
- [text setString:@""];
+ data += ((position.y - origin.y) * size.x);
+ for (UINT32 row = position.y; row < position.y + clip.y; row++, data += size.x)
+ {
+ if ((row < origin.y) || (row >= origin.y + size.y))
+ continue;
+
+ // render entire lines to get character alignment right
+ int attr = -1;
+ NSUInteger start = 0, length = 0;
+ for (UINT32 col = origin.x; col < origin.x + size.x; col++)
+ {
+ [[text mutableString] appendFormat:@"%c", data[col - origin.x].byte];
+ if ((start < length) && (attr != data[col - origin.x].attrib))
+ {
+ NSRange const run = NSMakeRange(start, length - start);
+ [text addAttribute:NSFontAttributeName
+ value:font
+ range:NSMakeRange(0, length)];
+ [text addAttribute:NSForegroundColorAttributeName
+ value:[self foregroundForAttribute:attr]
+ range:run];
+ NSRange const glyphs = [layoutManager glyphRangeForCharacterRange:run
+ actualCharacterRange:NULL];
+ NSRect const box = [layoutManager boundingRectForGlyphRange:glyphs
+ inTextContainer:textContainer];
+ [[self backgroundForAttribute:attr] set];
+ [NSBezierPath fillRect:NSMakeRect(box.origin.x,
+ row * fontHeight,
+ box.size.width,
+ fontHeight)];
+ start = length;
}
+ attr = data[col - origin.x].attrib;
+ length = [text length];
+ }
+ if (start < length)
+ {
+ NSRange const run = NSMakeRange(start, length - start);
+ [text addAttribute:NSFontAttributeName
+ value:font
+ range:NSMakeRange(0, length)];
+ [text addAttribute:NSForegroundColorAttributeName
+ value:[self foregroundForAttribute:attr]
+ range:run];
+ NSRange const glyphs = [layoutManager glyphRangeForCharacterRange:run
+ actualCharacterRange:NULL];
+ NSRect const box = [layoutManager boundingRectForGlyphRange:glyphs
+ inTextContainer:textContainer];
+ [[self backgroundForAttribute:attr] set];
+ [NSBezierPath fillRect:NSMakeRect(box.origin.x,
+ row * fontHeight,
+ box.size.width,
+ fontHeight)];
}
+ [layoutManager drawGlyphsForGlyphRange:[layoutManager glyphRangeForTextContainer:textContainer]
+ atPoint:NSMakePoint(0, row * fontHeight)];
+ [text deleteCharactersInRange:NSMakeRange(0, length)];
}
- [attributes release];
- [text release];
}
diff --git a/src/osd/modules/debugger/osx/debugosxdisassemblyview.m b/src/osd/modules/debugger/osx/debugosxdisassemblyview.m
index af0242b20b4..7a482cd8504 100644
--- a/src/osd/modules/debugger/osx/debugosxdisassemblyview.m
+++ b/src/osd/modules/debugger/osx/debugosxdisassemblyview.m
@@ -11,7 +11,6 @@
#import "debugosxdisassemblyview.h"
-#include "emucore.h"
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
#include "debug/debugvw.h"
diff --git a/src/osd/modules/debugger/osx/debugosxmemoryview.m b/src/osd/modules/debugger/osx/debugosxmemoryview.m
index 8477a8cb6fa..beee0fa6156 100644
--- a/src/osd/modules/debugger/osx/debugosxmemoryview.m
+++ b/src/osd/modules/debugger/osx/debugosxmemoryview.m
@@ -11,7 +11,6 @@
#import "debugosxmemoryview.h"
-#include "emucore.h"
#include "debug/debugcpu.h"
#include "debug/debugvw.h"
#include "debug/dvmemory.h"