Previous 199869 Revisions Next

r35023 Saturday 14th February, 2015 at 07:00:56 UTC by Vasantha Crabb
Far better handling of font metrics in Cocoa debugger, and more efficient drawing
[src/osd/modules/debugger/osx]debugosxdebugview.h debugosxdebugview.m debugosxdisassemblyview.m debugosxmemoryview.m

trunk/src/osd/modules/debugger/osx/debugosxdebugview.h
r243534r243535
4545
4646   NSFont         *font;
4747   CGFloat         fontWidth, fontHeight, fontAscent;
48
49   NSTextStorage   *text;
50   NSTextContainer   *textContainer;
51   NSLayoutManager   *layoutManager;
4852}
4953
5054+ (NSFont *)defaultFont;
trunk/src/osd/modules/debugger/osx/debugosxdebugview.m
r243534r243535
5858
5959- (debug_view_xy)convertLocation:(NSPoint)location {
6060   debug_view_xy position;
61   position.x = lround(floor(location.x / fontWidth));
61
6262   position.y = lround(floor(location.y / fontHeight));
63   if (position.y < 0)
64      position.y = 0;
65   else if (position.y >= totalHeight)
66      position.y = totalHeight - 1;
67
68   debug_view_xy const origin = view->visible_position();
69   debug_view_xy const size = view->visible_size();
70   debug_view_char const *data = view->viewdata();
71   if (!data || (position.y < origin.y) || (position.y >= origin.y + size.y))
72   {
73      // y coordinate outside visible area, x will be a guess
74      position.x = lround(floor(location.x / fontWidth));
75   }
76   else
77   {
78      data += ((position.y - view->visible_position().y) * view->visible_size().x);
79      int         attr = -1;
80      NSUInteger   start = 0, length = 0;
81      for (UINT32 col = origin.x; col < origin.x + size.x; col++)
82      {
83         [[text mutableString] appendFormat:@"%c", data[col - origin.x].byte];
84         if ((start < length) && (attr != data[col - origin.x].attrib))
85         {
86            NSRange const run = NSMakeRange(start, length - start);
87            [text addAttribute:NSFontAttributeName
88                      value:font
89                      range:NSMakeRange(0, length)];
90            [text addAttribute:NSForegroundColorAttributeName
91                      value:[self foregroundForAttribute:attr]
92                      range:run];
93            start = length;
94         }
95         attr = data[col - origin.x].attrib;
96         length = [text length];
97      }
98      if (start < length)
99      {
100         NSRange const run = NSMakeRange(start, length - start);
101         [text addAttribute:NSFontAttributeName
102                   value:font
103                   range:NSMakeRange(0, length)];
104         [text addAttribute:NSForegroundColorAttributeName
105                   value:[self foregroundForAttribute:attr]
106                   range:run];
107      }
108      CGFloat fraction;
109      NSUInteger const glyph = [layoutManager glyphIndexForPoint:NSMakePoint(location.x, fontHeight / 2)
110                                       inTextContainer:textContainer
111                           fractionOfDistanceThroughGlyph:&fraction];
112      position.x = [layoutManager characterIndexForGlyphAtIndex:glyph]; // FIXME: assumes 1:1 character mapping
113   }
63114   if (position.x < 0)
64115      position.x = 0;
65116   else if (position.x >= totalWidth)
66117      position.x = totalWidth - 1;
67   if (position.y < 0)
68      position.y = 0;
69   else if (position.y >= totalHeight)
70      position.y = totalHeight - 1;
118
71119   return position;
72120}
73121
r243534r243535
75123- (void)convertBounds:(NSRect)b toPosition:(debug_view_xy *)origin size:(debug_view_xy *)size {
76124   origin->x = lround(floor(b.origin.x / fontWidth));
77125   origin->y = lround(floor(b.origin.y / fontHeight));
126
127   // FIXME: this is not using proper font metrics horizontally
78128   size->x = lround(ceil((b.origin.x + b.size.width) / fontWidth)) - origin->x;
79129   size->y = lround(ceil((b.origin.y + b.size.height) / fontHeight)) - origin->y;
80130}
r243534r243535
107157      {
108158         debug_view_xy newPos = view->cursor_position();
109159         if ((newPos.x != oldPos.x) || (newPos.y != oldPos.y)) {
110            [self scrollRectToVisible:NSMakeRect(newPos.x * fontWidth,
160            [self scrollRectToVisible:NSMakeRect(newPos.x * fontWidth, // FIXME - use proper metrics
111161                                        newPos.y * fontHeight,
112162                                        fontWidth,
113163                                        fontHeight)];
r243534r243535
120170
121171
122172+ (NSFont *)defaultFont {
123   // maybe we should get the configured system fixed-width font...
124   return [NSFont fontWithName:@"Monaco" size:10];
173   return [NSFont userFixedPitchFontOfSize:0];
125174}
126175
127176
r243534r243535
138187   totalWidth = totalHeight = 0;
139188   originLeft = originTop = 0;
140189   [self setFont:[[self class] defaultFont]];
190   text = [[NSTextStorage alloc] init];
191   textContainer = [[NSTextContainer alloc] init];
192   layoutManager = [[NSLayoutManager alloc] init];
193   [layoutManager addTextContainer:textContainer];
194   [text addLayoutManager:layoutManager];
141195   return self;
142196}
143197
144198
145199- (void)dealloc {
146200   [[NSNotificationCenter defaultCenter] removeObserver:self];
147   if (font != nil)
148      [font release];
201   if (font != nil) [font release];
202   if (text != nil) [text release];
203   if (textContainer != nil) [textContainer release];
204   if (layoutManager != nil) [layoutManager release];
149205   [super dealloc];
150206}
151207
r243534r243535
156212   // resize our frame if the total size has changed
157213   newSize = view->total_size();
158214   if ((newSize.x != totalWidth) || (newSize.y != totalHeight)) {
159      [self setFrameSize:NSMakeSize(fontWidth * newSize.x, fontHeight * newSize.y)];
215      [self setFrameSize:NSMakeSize(fontWidth * newSize.x, fontHeight * newSize.y)]; // FIXME: metrics
160216      totalWidth = newSize.x;
161217      totalHeight = newSize.y;
162218   }
r243534r243535
221277      debug_view_xy pos;
222278      view->set_cursor_visible(true);
223279      pos = view->cursor_position();
224      [self scrollRectToVisible:NSMakeRect(pos.x * fontWidth, pos.y * fontHeight, fontWidth, fontHeight)];
280      [self scrollRectToVisible:NSMakeRect(pos.x * fontWidth, pos.y * fontHeight, fontWidth, fontHeight)]; // FIXME: metrics
225281      [self setNeedsDisplay:YES];
226282      return [super becomeFirstResponder];
227283   } else {
r243534r243535
266322
267323
268324- (void)drawRect:(NSRect)dirtyRect {
269   const debug_view_char   *base;
270   debug_view_xy         origin, size;
271   debug_view_xy         position, clip;
272   NSMutableString         *text;
273   NSMutableDictionary      *attributes;
274   UINT32               pass, row, col;
325   debug_view_xy position, clip;
275326
276327   // work out how much we need to draw
277328   [self recomputeVisible];
278   origin = view->visible_position();
279   size = view->visible_size();
329   debug_view_xy const origin = view->visible_position();
330   debug_view_xy const size = view->visible_size();
280331   [self convertBounds:dirtyRect toPosition:&position size:&clip];
281332
282333   // this gets the text for the whole visible area
283   base = view->viewdata();
284   if (!base)
334   debug_view_char const *data = view->viewdata();
335   if (!data)
285336      return;
286337
287   text = [[NSMutableString alloc] initWithCapacity:clip.x];
288   attributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:font, NSFontAttributeName, nil];
289   for (pass = 0; pass < 2; pass++) {
290      const debug_view_char *data = base + ((position.y - origin.y) * size.x);
291      for (row = position.y; row < position.y + clip.y; row++, data += size.x) {
292         int attr = -1;
338   data += ((position.y - origin.y) * size.x);
339   for (UINT32 row = position.y; row < position.y + clip.y; row++, data += size.x)
340   {
341      if ((row < origin.y) || (row >= origin.y + size.y))
342         continue;
293343
294         if ((row < origin.y) || (row >= origin.y + size.y))
295            continue;
296
297         // render entire lines to get character alignment right
298         for (col = origin.x; col < origin.x + size.x; col++) {
299            if ((attr != data[col - origin.x].attrib) && ([text length] > 0)) {
300               if (pass == 0) {
301                  [[self backgroundForAttribute:attr] set];
302                  [NSBezierPath fillRect:NSMakeRect((col - [text length]) * fontWidth,
303                                            row * fontHeight,
304                                            [text length] * fontWidth,
305                                            fontHeight)];
306               } else {
307                  [attributes setObject:[self foregroundForAttribute:attr]
308                              forKey:NSForegroundColorAttributeName];
309                  [text drawAtPoint:NSMakePoint((col - [text length]) * fontWidth, row * fontHeight)
310                     withAttributes:attributes];
311               }
312               [text setString:@""];
313            }
314            attr = data[col - origin.x].attrib;
315            [text appendFormat:@"%c", data[col - origin.x].byte];
344      // render entire lines to get character alignment right
345      int         attr = -1;
346      NSUInteger   start = 0, length = 0;
347      for (UINT32 col = origin.x; col < origin.x + size.x; col++)
348      {
349         [[text mutableString] appendFormat:@"%c", data[col - origin.x].byte];
350         if ((start < length) && (attr != data[col - origin.x].attrib))
351         {
352            NSRange const run = NSMakeRange(start, length - start);
353            [text addAttribute:NSFontAttributeName
354                      value:font
355                      range:NSMakeRange(0, length)];
356            [text addAttribute:NSForegroundColorAttributeName
357                      value:[self foregroundForAttribute:attr]
358                      range:run];
359            NSRange const glyphs = [layoutManager glyphRangeForCharacterRange:run
360                                              actualCharacterRange:NULL];
361            NSRect const box = [layoutManager boundingRectForGlyphRange:glyphs
362                                             inTextContainer:textContainer];
363            [[self backgroundForAttribute:attr] set];
364            [NSBezierPath fillRect:NSMakeRect(box.origin.x,
365                                      row * fontHeight,
366                                      box.size.width,
367                                      fontHeight)];
368            start = length;
316369         }
317         if ([text length] > 0) {
318            if (pass == 0) {
319               [[self backgroundForAttribute:attr] set];
320               [NSBezierPath fillRect:NSMakeRect((col - [text length]) * fontWidth,
321                                         row * fontHeight,
322                                         [text length] * fontWidth,
323                                         fontHeight)];
324            } else {
325               [attributes setObject:[self foregroundForAttribute:attr]
326                           forKey:NSForegroundColorAttributeName];
327               [text drawAtPoint:NSMakePoint((col - [text length]) * fontWidth, row * fontHeight)
328                  withAttributes:attributes];
329            }
330            [text setString:@""];
331         }
370         attr = data[col - origin.x].attrib;
371         length = [text length];
332372      }
373      if (start < length)
374      {
375         NSRange const run = NSMakeRange(start, length - start);
376         [text addAttribute:NSFontAttributeName
377                   value:font
378                   range:NSMakeRange(0, length)];
379         [text addAttribute:NSForegroundColorAttributeName
380                   value:[self foregroundForAttribute:attr]
381                   range:run];
382         NSRange const glyphs = [layoutManager glyphRangeForCharacterRange:run
383                                           actualCharacterRange:NULL];
384         NSRect const box = [layoutManager boundingRectForGlyphRange:glyphs
385                                          inTextContainer:textContainer];
386         [[self backgroundForAttribute:attr] set];
387         [NSBezierPath fillRect:NSMakeRect(box.origin.x,
388                                   row * fontHeight,
389                                   box.size.width,
390                                   fontHeight)];
391      }
392      [layoutManager drawGlyphsForGlyphRange:[layoutManager glyphRangeForTextContainer:textContainer]
393                              atPoint:NSMakePoint(0, row * fontHeight)];
394      [text deleteCharactersInRange:NSMakeRange(0, length)];
333395   }
334   [attributes release];
335   [text release];
336396}
337397
338398
trunk/src/osd/modules/debugger/osx/debugosxdisassemblyview.m
r243534r243535
1111
1212#import "debugosxdisassemblyview.h"
1313
14#include "emucore.h"
1514#include "debug/debugcon.h"
1615#include "debug/debugcpu.h"
1716#include "debug/debugvw.h"
trunk/src/osd/modules/debugger/osx/debugosxmemoryview.m
r243534r243535
1111
1212#import "debugosxmemoryview.h"
1313
14#include "emucore.h"
1514#include "debug/debugcpu.h"
1615#include "debug/debugvw.h"
1716#include "debug/dvmemory.h"


Previous 199869 Revisions Next


© 1997-2024 The MAME Team