mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 07:00:46 +00:00
Extract glyph generation code into separate class.
Plus some additional cleanup. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@26523 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
50f7974d7c
commit
f59bbe5aa8
8 changed files with 1295 additions and 844 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2008-05-13 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Headers/AppKit/NSGlyphGenerator.h,
|
||||
* Source/NSGlyphGenerator.m: New file.
|
||||
* Source/GNUmakefile: Add new files.
|
||||
* Headers/Additions/GNUstepGUI/GSLayoutManager_internal.h: More
|
||||
efficient memory usage for glyph runs.
|
||||
* Headers/Additions/GNUstepGUI/GSLayoutManager.h: Add ivar for
|
||||
glyph generator and some MacOSX methods.
|
||||
* Source/GSLayoutManager.m: Use objc_malloc, objc_free and
|
||||
objc_realloc. Move glyph generation into seperate class. Add
|
||||
documentation. General cleanup. Implement some of the additional
|
||||
methods.
|
||||
* Source/NSLayoutManager.m: Adopt to changes in super class.
|
||||
|
||||
2008-05-13 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSOpenPanel.m:
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <Foundation/NSObject.h>
|
||||
#include <Foundation/NSGeometry.h>
|
||||
#include <AppKit/NSFont.h>
|
||||
#include <AppKit/NSGlyphGenerator.h>
|
||||
|
||||
@class GSTypesetter;
|
||||
@class NSTextStorage,NSTextContainer;
|
||||
|
@ -44,10 +45,15 @@ typedef enum
|
|||
NSGlyphInscribeOverBelow = 4
|
||||
} NSGlyphInscription;
|
||||
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST)
|
||||
@interface GSLayoutManager : NSObject <NSGlyphStorage, NSCoding>
|
||||
#else
|
||||
@interface GSLayoutManager : NSObject
|
||||
#endif
|
||||
{
|
||||
@protected
|
||||
NSTextStorage *_textStorage;
|
||||
NSGlyphGenerator *_glyphGenerator;
|
||||
|
||||
id _delegate;
|
||||
|
||||
|
@ -101,6 +107,8 @@ how it's supposed to work. It's functional and correct, but it isn't fast. */
|
|||
- (void) setTextStorage: (NSTextStorage *)aTextStorage;
|
||||
- (void) replaceTextStorage: (NSTextStorage *)newTextStorage;
|
||||
|
||||
- (NSGlyphGenerator *) glyphGenerator;
|
||||
- (void) setGlyphGenerator: (NSGlyphGenerator *)glyphGenerator;
|
||||
|
||||
- (id) delegate;
|
||||
- (void) setDelegate: (id)aDelegate;
|
||||
|
@ -216,9 +224,11 @@ it isn't NULL. */
|
|||
/* These can be used to set arbitrary tags on individual glyphs.
|
||||
Non-negative tags are reserved. You must provide storage yourself (by
|
||||
subclassing). */
|
||||
#if !OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST)
|
||||
- (void) setIntAttribute: (int)attributeTag
|
||||
value: (int)anInt
|
||||
forGlyphAtIndex: (unsigned int)glyphIndex;
|
||||
#endif
|
||||
- (int) intAttribute: (int)attributeTag
|
||||
forGlyphAtIndex: (unsigned int)glyphIndex;
|
||||
|
||||
|
|
|
@ -99,11 +99,12 @@ typedef struct
|
|||
typedef struct GSLayoutManager_glyph_run_s
|
||||
{
|
||||
glyph_run_head_t head;
|
||||
// Pointer to the previous leaf. Invariant: t->head->next->prev == t
|
||||
glyph_run_head_t *prev;
|
||||
|
||||
/* Zero-based, so it's really the number of heads in addition to the
|
||||
one included in glyph_run_t. */
|
||||
int level;
|
||||
unsigned int level:4;
|
||||
|
||||
/* All glyph-generation-affecting attributes are same as last run. This
|
||||
doesn't have to be set if a run is continued, but if it is set, it must
|
||||
|
@ -121,25 +122,19 @@ typedef struct GSLayoutManager_glyph_run_s
|
|||
/* TODO2: these aren't filled in or used anywhere yet */
|
||||
unsigned int bidi_level:6;
|
||||
|
||||
/* Font for this run. */
|
||||
NSFont *font;
|
||||
int ligature;
|
||||
int ligature:5;
|
||||
|
||||
/* YES if there's an explicit kern attribute. Currently, ligatures aren't
|
||||
used when explicit kerning is available (TODO). */
|
||||
BOOL explicit_kern;
|
||||
unsigned int explicit_kern:1;
|
||||
|
||||
/* Font for this run. */
|
||||
NSFont *font;
|
||||
|
||||
glyph_t *glyphs;
|
||||
} glyph_run_t;
|
||||
|
||||
|
||||
@interface GSLayoutManager (backend)
|
||||
-(unsigned int) _findSafeBreakMovingBackwardFrom: (unsigned int)ch;
|
||||
-(unsigned int) _findSafeBreakMovingForwardFrom: (unsigned int)ch;
|
||||
-(void) _generateGlyphsForRun: (glyph_run_t *)run at: (unsigned int)pos;
|
||||
@end
|
||||
|
||||
|
||||
/* All positions and lengths in glyphs */
|
||||
typedef struct
|
||||
{
|
||||
|
|
74
Headers/AppKit/NSGlyphGenerator.h
Normal file
74
Headers/AppKit/NSGlyphGenerator.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* -*-objc-*-
|
||||
NSGlyphGenerator.h
|
||||
|
||||
Interfaces for glyph generation and storage.
|
||||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Author: H. N. Schaller <hns@computer.org>
|
||||
Date: Jun 2006 - aligned with 10.4
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GNUstep_H_NSGlyphGenerator
|
||||
#define _GNUstep_H_NSGlyphGenerator
|
||||
#import <GNUstepBase/GSVersionMacros.h>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
// define NSGlyph
|
||||
#import <AppKit/NSFont.h>
|
||||
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST)
|
||||
|
||||
enum
|
||||
{
|
||||
NSShowControlGlyphs = 1,
|
||||
NSShowInvisibleGlyphs = 2,
|
||||
NSWantsBidiLevels = 4
|
||||
};
|
||||
|
||||
@protocol NSGlyphStorage
|
||||
|
||||
- (NSAttributedString*) attributedString;
|
||||
- (void) insertGlyphs: (const NSGlyph*)glyphs
|
||||
length: (NSUInteger)length
|
||||
forStartingGlyphAtIndex: (NSUInteger)glyph
|
||||
characterIndex: (NSUInteger)index;
|
||||
- (NSUInteger) layoutOptions;
|
||||
- (void) setIntAttribute: (NSInteger)tag
|
||||
value: (NSInteger)value
|
||||
forGlyphAtIndex: (NSUInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSGlyphGenerator : NSObject
|
||||
|
||||
+ (id) sharedGlyphGenerator;
|
||||
- (void) generateGlyphsForGlyphStorage: (id <NSGlyphStorage>)storage
|
||||
desiredNumberOfCharacters: (NSUInteger)num
|
||||
glyphIndex: (NSUInteger*)glyph
|
||||
characterIndex: (NSUInteger*)index;
|
||||
|
||||
@end
|
||||
|
||||
#endif // MAC_OS_X_VERSION_10_3
|
||||
|
||||
#endif // _GNUstep_H_NSGlyphGenerator
|
|
@ -94,6 +94,7 @@ NSFontManager.m \
|
|||
NSFontPanel.m \
|
||||
NSForm.m \
|
||||
NSFormCell.m \
|
||||
NSGlyphGenerator.m \
|
||||
NSGraphicsContext.m \
|
||||
NSHelpPanel.m \
|
||||
NSHelpManager.m \
|
||||
|
@ -287,6 +288,7 @@ NSFontManager.h \
|
|||
NSFontPanel.h \
|
||||
NSForm.h \
|
||||
NSFormCell.h \
|
||||
NSGlyphGenerator.h \
|
||||
NSGraphicsContext.h \
|
||||
NSHelpPanel.h \
|
||||
NSHelpManager.h \
|
||||
|
|
File diff suppressed because it is too large
Load diff
281
Source/NSGlyphGenerator.m
Normal file
281
Source/NSGlyphGenerator.m
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
NSGlyphGenerator.m
|
||||
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
Author: Fred Kiefer <fredkiefer@gmx.de>
|
||||
Date: April 2008
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <GNUstepBase/Unicode.h>
|
||||
|
||||
#include "AppKit/NSAttributedString.h"
|
||||
#include "AppKit/NSFont.h"
|
||||
#include "AppKit/NSGlyphGenerator.h"
|
||||
/* just for NSAttachmentCharacter */
|
||||
#include "AppKit/NSTextAttachment.h"
|
||||
#include "GNUstepGUI/GSFontInfo.h"
|
||||
|
||||
static NSGlyphGenerator* instance;
|
||||
|
||||
@interface NSGlyphGenerator (Private)
|
||||
- (NSFont *) fontForCharactersWithAttributes: (NSDictionary *)attributes;
|
||||
@end
|
||||
|
||||
@implementation NSGlyphGenerator
|
||||
|
||||
+ (id) sharedGlyphGenerator
|
||||
{
|
||||
if (!instance)
|
||||
instance = [[NSGlyphGenerator alloc] init];
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Send a run of glyphs where each glyph corresponds to one character.
|
||||
#define SEND_GLYPHS() \
|
||||
{ \
|
||||
NSUInteger length; \
|
||||
\
|
||||
if ((length = g - glyphs)) \
|
||||
{ \
|
||||
[storage insertGlyphs: glyphs \
|
||||
length: length \
|
||||
forStartingGlyphAtIndex: *glyph \
|
||||
characterIndex: *index]; \
|
||||
*index += i - cstart + 1; \
|
||||
*glyph += length; \
|
||||
g = glyphs; \
|
||||
cstart = i + 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
This is a fairly simple implementation. It will use "ff", "fl", "fi",
|
||||
"ffl", and "ffi" ligatures if available.
|
||||
|
||||
TODO: how should words like "pfffffffffff" be handled?
|
||||
|
||||
0066 'f'
|
||||
0069 'i'
|
||||
006c 'l'
|
||||
fb00 'ff'
|
||||
fb01 'fi'
|
||||
fb02 'fl'
|
||||
fb03 'ffi'
|
||||
fb04 'ffl'
|
||||
*/
|
||||
- (void) generateGlyphsForGlyphStorage: (id <NSGlyphStorage>)storage
|
||||
desiredNumberOfCharacters: (NSUInteger)num
|
||||
glyphIndex: (NSUInteger*)glyph
|
||||
characterIndex: (NSUInteger*)index
|
||||
{
|
||||
// Try to get enough space for all glyphs
|
||||
NSGlyph glyphs[2 * num];
|
||||
NSGlyph *g;
|
||||
NSGlyph gl;
|
||||
NSAttributedString *attrstr = [storage attributedString];
|
||||
GSFontInfo *fi;
|
||||
int i;
|
||||
unichar buf[num];
|
||||
unsigned int cstart = 0;
|
||||
NSRange maxRange = NSMakeRange(*index, num);
|
||||
NSRange curRange;
|
||||
NSDictionary *attributes;
|
||||
NSNumber *n;
|
||||
int ligature;
|
||||
BOOL surr;
|
||||
NSCharacterSet *cs = [NSCharacterSet controlCharacterSet];
|
||||
SEL cim_sel = @selector(characterIsMember:);
|
||||
BOOL (*characterIsMember)(id, SEL, unichar)
|
||||
= (BOOL(*)(id, SEL, unichar)) [cs methodForSelector: cim_sel];
|
||||
SEL gfc_sel = @selector(glyphForCharacter:);
|
||||
NSGlyph (*glyphForCharacter)(id, SEL, unichar);
|
||||
|
||||
[[attrstr string] getCharacters: buf range: maxRange];
|
||||
attributes = [attrstr attributesAtIndex: *index
|
||||
longestEffectiveRange: &curRange
|
||||
inRange: maxRange];
|
||||
fi = [[self fontForCharactersWithAttributes: attributes] fontInfo];
|
||||
glyphForCharacter = (NSGlyph(*)(id, SEL, unichar)) [fi methodForSelector: gfc_sel];
|
||||
|
||||
n = [attributes objectForKey: NSLigatureAttributeName];
|
||||
if (n)
|
||||
ligature = [n intValue];
|
||||
else
|
||||
ligature = 1;
|
||||
|
||||
g = glyphs;
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
unsigned int ch, ch2;
|
||||
|
||||
ch = buf[i];
|
||||
if (characterIsMember(cs, cim_sel, ch))
|
||||
{
|
||||
*g = NSControlGlyph;
|
||||
g++;
|
||||
continue;
|
||||
}
|
||||
if (ch == NSAttachmentCharacter)
|
||||
{
|
||||
*g = GSAttachmentGlyph;
|
||||
g++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Simple ligature processing
|
||||
if ((ligature >= 1) && (i + 1 < num))
|
||||
{
|
||||
ch2 = buf[i + 1];
|
||||
|
||||
if (ch == 'f')
|
||||
{
|
||||
if ((i + 2 < num) && (ch2 == 'f'))
|
||||
{
|
||||
// ffl
|
||||
if ((buf[i + 2] == 'l')
|
||||
&& (NSNullGlyph != (gl = glyphForCharacter(fi, gfc_sel, 0xfb04))))
|
||||
{
|
||||
*g = gl;
|
||||
g++;
|
||||
i += 2;
|
||||
SEND_GLYPHS();
|
||||
continue;
|
||||
}
|
||||
// ffi
|
||||
if ((buf[i + 2] == 'i')
|
||||
&& (NSNullGlyph != (gl = glyphForCharacter(fi, gfc_sel, 0xfb03))))
|
||||
{
|
||||
*g = gl;
|
||||
g++;
|
||||
i += 2;
|
||||
SEND_GLYPHS();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// ff
|
||||
if ((ch2 == 'f')
|
||||
&& (NSNullGlyph != (gl = glyphForCharacter(fi, gfc_sel, 0xfb00))))
|
||||
{
|
||||
*g = gl;
|
||||
g++;
|
||||
i++;
|
||||
SEND_GLYPHS();
|
||||
continue;
|
||||
}
|
||||
// fi
|
||||
if ((ch2 == 'i')
|
||||
&& (NSNullGlyph != (gl = glyphForCharacter(fi, gfc_sel, 0xfb01))))
|
||||
{
|
||||
*g = gl;
|
||||
g++;
|
||||
i++;
|
||||
SEND_GLYPHS();
|
||||
continue;
|
||||
}
|
||||
// fl
|
||||
if ((ch2 == 'l')
|
||||
&& (NSNullGlyph != (gl = glyphForCharacter(fi, gfc_sel, 0xfb02))))
|
||||
{
|
||||
*g = gl;
|
||||
g++;
|
||||
i++;
|
||||
SEND_GLYPHS();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
surr = NO;
|
||||
// Check for surrogate pairs
|
||||
if (ch >= 0xd800 && ch <= 0xdfff)
|
||||
{
|
||||
if (ch >= 0xd800 && ch < 0xdc00
|
||||
&& (i + 1 < num) && (ch2 = buf[i + 1]) >= 0xdc00
|
||||
&& ch2 <= 0xdfff)
|
||||
{
|
||||
ch = ((ch & 0x3ff) << 10) + (ch2 & 0x3ff) + 0x10000;
|
||||
i++;
|
||||
surr = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = 0xfffd;
|
||||
}
|
||||
}
|
||||
|
||||
gl = glyphForCharacter(fi, gfc_sel, ch);
|
||||
if (gl != NSNullGlyph)
|
||||
{
|
||||
*g = gl;
|
||||
g++;
|
||||
if (surr)
|
||||
SEND_GLYPHS();
|
||||
}
|
||||
else if (ch < 0x10000)
|
||||
{
|
||||
unichar *decomp;
|
||||
|
||||
decomp = uni_is_decomp(ch);
|
||||
if (decomp)
|
||||
{
|
||||
for (; *decomp; decomp++)
|
||||
{
|
||||
gl = glyphForCharacter(fi, gfc_sel, *decomp);
|
||||
if (gl == NSNullGlyph)
|
||||
{
|
||||
break;
|
||||
}
|
||||
*g = gl;
|
||||
g++;
|
||||
SEND_GLYPHS();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// On a NSNullGLyph, send all previous glyphs
|
||||
SEND_GLYPHS();
|
||||
}
|
||||
}
|
||||
|
||||
// Send all remaining glyphs
|
||||
SEND_GLYPHS();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSGlyphGenerator (Private)
|
||||
|
||||
- (NSFont *) fontForCharactersWithAttributes: (NSDictionary *)attributes
|
||||
{
|
||||
NSFont *f = [attributes valueForKey: NSFontAttributeName];
|
||||
if (!f)
|
||||
f = [NSFont userFontOfSize: 0];
|
||||
|
||||
//f = [storage substituteFontForFont: f];
|
||||
return f;
|
||||
}
|
||||
|
||||
@end
|
|
@ -383,7 +383,7 @@ container? necessary? */
|
|||
if (num_rects == rect_array_size)
|
||||
{
|
||||
rect_array_size += 4;
|
||||
rect_array = realloc(rect_array, sizeof(NSRect) * rect_array_size);
|
||||
rect_array = objc_realloc(rect_array, sizeof(NSRect) * rect_array_size);
|
||||
}
|
||||
rect_array[num_rects++] = r;
|
||||
}
|
||||
|
@ -2036,12 +2036,12 @@ this file describes this.
|
|||
}
|
||||
if (lf->points)
|
||||
{
|
||||
free(lf->points);
|
||||
objc_free(lf->points);
|
||||
lf->points = NULL;
|
||||
}
|
||||
if (lf->attachments)
|
||||
{
|
||||
free(lf->attachments);
|
||||
objc_free(lf->attachments);
|
||||
lf->attachments = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -2156,12 +2156,12 @@ no_soft_invalidation:
|
|||
{
|
||||
if (lf->points)
|
||||
{
|
||||
free(lf->points);
|
||||
objc_free(lf->points);
|
||||
lf->points = NULL;
|
||||
}
|
||||
if (lf->attachments)
|
||||
{
|
||||
free(lf->attachments);
|
||||
objc_free(lf->attachments);
|
||||
lf->attachments = NULL;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue