CtrlCore: Cocoa font features (RenderCharSys, GetData), Draw: Font caching optimized, Core: FoldHash function

git-svn-id: svn://ultimatepp.org/upp/trunk@12177 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2018-08-21 12:42:55 +00:00
parent 8b045bc99d
commit 5a44eeb5a7
12 changed files with 137 additions and 29 deletions

View file

@ -283,3 +283,8 @@ int fast_memcmp(const char *a, const char *b, size_t len)
return memcmp(a, b, len);
}
#endif
inline dword FoldHash(dword h)
{
return h - SwapEndian32((dword)h);
}

View file

@ -153,7 +153,9 @@ struct CocoTop;
struct MMCtrl;
struct MMImp;
#define GUIPLATFORM_CTRL_TOP_DECLS CocoTop *coco = NULL; One<DrawDragRectInfo> dr;
#define GUIPLATFORM_CTRL_TOP_DECLS \
CocoTop *coco = NULL; \
One<DrawDragRectInfo> dr; \
#define GUIPLATFORM_CTRL_DECLS_INCLUDE <CtrlCore/CocoCtrl.h>

View file

@ -14,11 +14,16 @@
@implementation CocoWindow
- (void)becomeKeyWindow {
[super becomeKeyWindow];
}
- (BOOL)canBecomeKeyWindow {
return active && ctrl && ctrl->IsEnabled();
}
- (BOOL)canBecomeMainWindow {
LLOG("canBecomeMainWindow " << Upp::Name(ctrl) << ", owner " << Upp::Name(ctrl->GetOwner()));
return active && ctrl && ctrl->IsEnabled() && dynamic_cast<Upp::TopWindow *>(~ctrl) && !ctrl->GetOwner();
}
@ -81,32 +86,33 @@ NSRect DesktopRect(const Upp::Rect& r)
void Upp::Ctrl::Create(Ctrl *owner, dword style, bool active)
{
top = new Top;
top->coco = new CocoTop;
top->coco->owner = owner;
NSRect frame = DesktopRect(GetRect());
CocoWindow *window = [[CocoWindow alloc] initWithContentRect:frame styleMask: style
backing:NSBackingStoreBuffered defer:false];
top->coco->window = window;
if(owner && owner->top && owner->top->coco)
[owner->top->coco->window addChildWindow:window ordered:NSWindowAbove];
window->ctrl = this;
window->active = active;
window.backgroundColor = nil;
CocoView *view = [[[CocoView alloc] initWithFrame:frame] autorelease];
view->ctrl = this;
top->coco->view = view;
[window setContentView:view];
[window setDelegate:view];
[window setAcceptsMouseMovedEvents:YES];
[window makeFirstResponder:view];
[window makeKeyAndOrderFront:view];
top = new Top;
top->coco = new CocoTop;
top->coco->window = window;
top->coco->view = view;
top->coco->owner = owner;
MMCtrl::SyncRect(view);
isopen = true;
mmtopctrl.Add(this);
if(owner && owner->top && owner->top->coco)
[owner->top->coco->window addChildWindow:window ordered:NSWindowAbove];
}
void Upp::Ctrl::WndDestroy()
@ -159,8 +165,27 @@ bool Upp::Ctrl::IsWndOpen() const {
void Upp::Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost)
{
Create(owner, NSWindowStyleMaskBorderless, false);
Create(owner, NSWindowStyleMaskBorderless, 0*activate);
popup = true;
if(activate) {
#if 0
NSWindow *window = top->coco->window;
[window setBackgroundColor:[NSColor clearColor]];
[window setOpaque:NO];
[window setStyleMask:NSResizableWindowMask | NSTitledWindowMask | NSFullSizeContentViewWindowMask];
[window setMovableByWindowBackground:YES];
[window setTitlebarAppearsTransparent:YES];
[window setTitleVisibility:NSWindowTitleHidden];
[window setShowsToolbarButton:NO];
[window standardWindowButton:NSWindowFullScreenButton].hidden = YES;
[window standardWindowButton:NSWindowMiniaturizeButton].hidden = YES;
[window standardWindowButton:NSWindowCloseButton].hidden = YES;
[window standardWindowButton:NSWindowZoomButton].hidden = YES;
[window makeKeyWindow];
// [window setHasShadow:YES];
#endif
ActivateWnd();
}
}
Upp::dword Upp::TopWindow::GetMMStyle() const
@ -182,8 +207,12 @@ void Upp::TopWindow::Open(Ctrl *owner)
: GetPrimaryWorkArea())
.CenterRect(GetRect().GetSize()));
Create(owner, GetMMStyle(), true);
ActivateWnd();
SyncCaption();
SyncSizeHints();
PlaceFocus();
// if(top)
// top->placefocus = true;
}
void Upp::TopWindow::Open()

View file

@ -52,6 +52,14 @@ CTFontRef CT_Font(Font fnt)
return e.ctfont;
}
CGGlyph GetCharGlyph(CTFontRef ctfont, int chr)
{
CGGlyph glyph_index;
UniChar h = chr;
CTFontGetGlyphsForCharacters(ctfont, &h, &glyph_index, 1);
return glyph_index;
}
GlyphInfo GetGlyphInfoSys(CTFontRef ctfont, int chr)
{
GlyphInfo gi;
@ -59,9 +67,7 @@ GlyphInfo GetGlyphInfoSys(CTFontRef ctfont, int chr)
gi.width = 0x8000;
if(ctfont) {
LTIMING("GetGlyphInfoSys 2");
CGGlyph glyph_index;
UniChar h = chr;
CTFontGetGlyphsForCharacters(ctfont, &h, &glyph_index, 1);
CGGlyph glyph_index = GetCharGlyph(ctfont, chr);
if(glyph_index) {
CGSize advance;
CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, &glyph_index, &advance, 1);
@ -100,10 +106,15 @@ CommonFontInfo GetFontInfoSys(Font font)
fi.default_char = '?';
fi.fixedpitch = CTFontGetSymbolicTraits(ctfont) & kCTFontMonoSpaceTrait;
fi.ttf = true;
// TODO: PATH for data
// if(path.GetCount() < 250)
// strcpy(fi.path, ~path);
// else
CFRef<CTFontDescriptorRef> fd = CTFontCopyFontDescriptor(ctfont);
CFRef<CFURLRef> url = (CFURLRef)CTFontDescriptorCopyAttribute(fd, kCTFontURLAttribute);
CFRef<CFStringRef> path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
String p = ToString(path);
if(p.GetCount() < 250)
strcpy(fi.path, ~p);
else
*fi.path = 0;
}
return fi;
@ -156,13 +167,53 @@ Vector<FaceInfo> GetAllFacesSys()
}
String GetFontDataSys(Font font)
{ // TODO! CFUrl?
return Null;
{
return LoadFile(font.Fi().path);
}
void RenderCharacterSys(FontGlyphConsumer& sw, double x, double y, int ch, Font fnt)
struct sCGPathTarget {
double x, y;
FontGlyphConsumer *sw;
};
static void convertCGPathToQPainterPath(void *info, const CGPathElement *e)
{
// TODO!
auto t = (sCGPathTarget *)info;
switch(e->type) {
case kCGPathElementMoveToPoint:
t->sw->Move(Pointf(e->points[0].x + t->x, e->points[0].y + t->y));
break;
case kCGPathElementAddLineToPoint:
t->sw->Line(Pointf(e->points[0].x + t->x, e->points[0].y + t->y));
break;
case kCGPathElementAddQuadCurveToPoint:
t->sw->Quadratic(Pointf(e->points[0].x + t->x, e->points[0].y + t->y),
Pointf(e->points[1].x + t->x, e->points[1].y + t->y));
break;
case kCGPathElementAddCurveToPoint:
t->sw->Cubic(Pointf(e->points[0].x + t->x, e->points[0].y + t->y),
Pointf(e->points[1].x + t->x, e->points[1].y + t->y),
Pointf(e->points[2].x + t->x, e->points[2].y + t->y));
break;
case kCGPathElementCloseSubpath:
t->sw->Close();
break;
}
}
void RenderCharacterSys(FontGlyphConsumer& sw, double x, double y, int chr, Font font)
{
CGAffineTransform cgMatrix = CGAffineTransformIdentity;
cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1);
CTFontRef ctfont = CT_Font(font);
CGGlyph glyph_index = GetCharGlyph(ctfont, chr);
CFRef<CGPathRef> cgpath = CTFontCreatePathForGlyph(ctfont, glyph_index, &cgMatrix);
sCGPathTarget t;
t.x = x;
t.y = y + font.GetAscent();
t.sw = &sw;
CGPathApply(cgpath, &t, convertCGPathToQPainterPath);
}
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink,

View file

@ -68,6 +68,7 @@ struct MMImp {
view->ctrl->DispatchMouse(event, p, 120 * sgn(zd));
return false;
}
static bool MouseDownEvent(CocoView *view, NSEvent *e, int button)
{
static int clicktime = msecs() - 100000;
@ -146,7 +147,13 @@ struct MMImp {
static void BecomeKey(Upp::Ctrl *ctrl)
{
LLOG("Become key " << Upp::Name(ctrl));
ctrl->ActivateWnd();
/* auto tw = dynamic_cast<TopWindow *>(ctrl);
if(tw && ctrl->top && ctrl->top->placefocus) {
tw->PlaceFocus();
ctrl->top->placefocus = false;
}*/
}
static void ResignKey(Upp::Ctrl *ctrl)

View file

@ -1,5 +1,7 @@
//$ class TopWindow {
protected:
friend struct MMImp;
dword GetMMStyle() const;
virtual void MMClose() { WhenClose(); }

View file

@ -2,7 +2,7 @@
namespace Upp {
#define LLOG(x) // DLOG(x)
#define LLOG(x) // DLOG(x)
Ptr<Ctrl> Ctrl::eventCtrl;
Ptr<Ctrl> Ctrl::mouseCtrl;

View file

@ -2,7 +2,7 @@
namespace Upp {
#define LLOG(x) // DLOG(x)
#define LLOG(x) // DLOG(x)
String TopWindow::GetDesc() const
{

View file

@ -1,5 +1,7 @@
sooner:
- reference/Reports - missing text
- opening FindInFiles, then selecting folder - pushing buttons does not exit dialog
- package organizer initial size too small

View file

@ -24,7 +24,11 @@ BorderFrame& XPMenuFrame()
CtrlFrame& MenuFrame()
{
#ifdef PLATFORM_COCOA
return NullFrame();
#else
return GUI_GlobalStyle() >= GUISTYLE_XP ? (CtrlFrame&)XPMenuFrame() : (CtrlFrame&)OutsetFrame();
#endif
}
CH_STYLE(MenuBar, Style, StyleDefault)
@ -447,6 +451,7 @@ void MenuBar::SetActiveSubmenu(MenuBar *sm, Ctrl *item)
void MenuBar::SubmenuClose()
{
LLOG("SubmenuClose");
if(parentmenu && parentmenu->GetActiveSubmenu() == this)
parentmenu->SetActiveSubmenu(NULL, NULL);
else {

View file

@ -391,11 +391,16 @@ struct CharEntry {
CharEntry fc_cache_global[4093];
inline dword GlyphHash(Font font, int chr)
{
return FoldHash(CombineHash(font.GetHashValue(), chr));
}
bool IsNormal(Font font, int chr)
{
Mutex::Lock __(sFontLock);
font.RealizeStd();
CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093];
CharEntry& e = fc_cache_global[GlyphHash(font, chr) % 4093];
if(e.font == font.AsInt64() || e.chr == chr)
return e.info.IsNormal();
return GetGlyphInfoSys(font, chr).IsNormal();
@ -433,7 +438,7 @@ thread__ CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
font.RealizeStd();
unsigned hash = CombineHash(font.GetHashValue(), chr);
unsigned hash = GlyphHash(font, chr);
CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
@ -499,12 +504,12 @@ struct FontEntry {
int64 font;
};
thread__ FontEntry fi_cache[64];
thread__ FontEntry fi_cache[63];
const CommonFontInfo& GetFontInfo(Font font)
{
font.RealizeStd();
unsigned hash = font.GetHashValue() & 63;
unsigned hash = FoldHash(font.GetHashValue()) % 63;
FontEntry& e = fi_cache[hash];
if(e.font != font.AsInt64()) {
Mutex::Lock __(sFontLock);

View file

@ -357,9 +357,9 @@ bool RenderOutline(const FT_Outline& outline, FontGlyphConsumer& path, double xx
FT_Vector vec1, vec2;
if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
return false;
vec1.x = point[0].x;
vec1.x = point[0].x;
vec1.y = point[0].y;
vec2.x = point[1].x;
vec2.x = point[1].x;
vec2.y = point[1].y;
point += 2;
tags += 2;