From 2ac7a45b4aa99cbbb23c95bbf408615686b9f2ec Mon Sep 17 00:00:00 2001 From: cxl Date: Fri, 20 Nov 2020 13:19:54 +0000 Subject: [PATCH] CtrlCore, Draw: Cocoa font handling moved to Draw git-svn-id: svn://ultimatepp.org/upp/trunk@15471 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/CoSort.h | 4 +- uppsrc/CtrlCore/CocoDrawText.mm | 262 +------------------------ uppsrc/CtrlCore/CocoMM.h | 1 + uppsrc/CtrlCore/CocoUtil.mm | 24 --- uppsrc/CtrlCore/CtrlCore.upp | 3 - uppsrc/Draw/Draw.upp | 3 + uppsrc/Draw/FontCoco.mm | 325 ++++++++++++++++++++++++++++++++ uppsrc/ide/OnlineSearch.cpp | 2 +- 8 files changed, 333 insertions(+), 291 deletions(-) delete mode 100644 uppsrc/CtrlCore/CocoUtil.mm create mode 100644 uppsrc/Draw/FontCoco.mm diff --git a/uppsrc/Core/CoSort.h b/uppsrc/Core/CoSort.h index 38a9c9c31..1c4d57e1d 100644 --- a/uppsrc/Core/CoSort.h +++ b/uppsrc/Core/CoSort.h @@ -46,12 +46,12 @@ void CoSort__(CoWork& cw, I l, I h, const Less& less) int count_h = h - ih - 1; if(count_l < count_h) { // recurse on smaller partition, tail on larger - cw & [=, &cw] { CoSort__(l, i, less); }; + cw & [=, &cw] { CoSort__(cw, l, i, less); }; l = ih + 1; count = count_h; } else { - cw & [=, &cw] { CoSort__(ih + 1, h, less); }; + cw & [=, &cw] { CoSort__(cw, ih + 1, h, less); }; h = i; count = count_l; } diff --git a/uppsrc/CtrlCore/CocoDrawText.mm b/uppsrc/CtrlCore/CocoDrawText.mm index 85ddf283d..0b20c5553 100644 --- a/uppsrc/CtrlCore/CocoDrawText.mm +++ b/uppsrc/CtrlCore/CocoDrawText.mm @@ -7,267 +7,7 @@ namespace Upp { -CTFontRef CT_Font0(Font fnt, bool& synth) -{ - CFRef s = CFStringCreateWithCString(NULL, ~fnt.GetFaceName(), kCFStringEncodingUTF8); - CFRef ctfont0 = CTFontCreateWithName(s, fnt.GetHeight(), NULL); - synth = false; - if(fnt.IsItalic() || fnt.IsBold()) { - CTFontSymbolicTraits t = 0; - if(fnt.IsBold()) - t |= kCTFontBoldTrait; - if(fnt.IsItalic()) - t |= kCTFontItalicTrait; - CFRef ctfont = CTFontCreateCopyWithSymbolicTraits(ctfont0, fnt.GetHeight(), - NULL, t, t); - if(ctfont) - return ctfont.Detach(); - synth = true; - } - return ctfont0.Detach(); -} - -CTFontRef CT_Font(Font fnt, bool& synth) -{ - struct Entry { - Font font; - CTFontRef ctfont = NULL; - bool synth = false; - - void Free() { if(ctfont) CFRelease(ctfont); ctfont = NULL; } - - Entry() { font.Height(-22222); } - ~Entry() { Free(); } - }; - - const int FONTCACHE = 64; - static Entry cache[FONTCACHE]; - for(int i = 0; i < FONTCACHE; i++) - if(cache[i].font == fnt) { - synth = cache[i].synth; - return cache[i].ctfont; - } - Entry& e = cache[Random(FONTCACHE)]; - e.Free(); - e.font = fnt; - e.ctfont = CT_Font0(fnt, synth); - e.synth = synth; - 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, bool bold_synth, CGRect *bounds = NULL) -{ - GlyphInfo gi; - gi.lspc = gi.rspc = 0; - gi.width = 0x8000; - if(ctfont) { - LTIMING("GetGlyphInfoSys 2"); - CGGlyph glyph_index = GetCharGlyph(ctfont, chr); - if(glyph_index) { - CGSize advance; - CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, &glyph_index, &advance, 1); - gi.width = ceil(advance.width); - gi.lspc = gi.rspc = 0; // TODO! (using bounding box?) - gi.glyphi = glyph_index; - if(bold_synth) - gi.width++; - if(bounds) - CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontOrientationHorizontal, - &glyph_index, bounds, 1); - - } - } - return gi; -} - -CommonFontInfo GetFontInfoSys(Font font) -{ - CommonFontInfo fi; - String path; - bool synth; - CTFontRef ctfont = CT_Font(font, synth); - if(ctfont) { - #if 0 - DDUMP(font); - DDUMP(CTFontGetSize(ctfont)); - DDUMP(CTFontGetAscent(ctfont)); - DDUMP(CTFontGetDescent(ctfont)); - DDUMP(); - DDUMP(CTFontGetXHeight(ctfont)); - DDUMP(CTFontGetUnderlinePosition(ctfont)); - DDUMP(MakeRect(CTFontGetBoundingBox(ctfont))); - DDUMPHEX(CTFontGetSymbolicTraits(ctfont)); - DDUMP(font); - CGRect cr = CTFontGetBoundingBox(ctfont); - DDUMP(cr.origin.y); - DDUMP(cr.size.height); - DDUMP(cr.origin.y + cr.size.height); - #endif - fi.descent = ceil(CTFontGetDescent(ctfont)); - fi.ascent = ceil(CTFontGetAscent(ctfont)); - fi.external = ceil(CTFontGetLeading(ctfont)); - - // Some MacOS fonts have really weird ascent/descents (namely stadard GUI font...) - // let us fix it by testing typical charactes bounding boxes - - static WString descent_test = "yjgp"; - CGRect bb; - for(int i = 0; i < descent_test.GetCount(); i++) - if(GetGlyphInfoSys(ctfont, descent_test[i], synth && font.IsBold(), &bb).IsNormal()) - fi.descent = max(fi.descent, (int)ceil(-bb.origin.y)); - - int ascent = fi.ascent; - static WString ascent_test = "ÀÁÂÃÄË"; - for(int i = 0; i < ascent_test.GetCount(); i++) - if(GetGlyphInfoSys(ctfont, ascent_test[i], synth && font.IsBold(), &bb).IsNormal()) - ascent = max(ascent, (int)ceil(bb.origin.y + bb.size.height)); - - fi.ascent = ascent; - - fi.internal = 0; - fi.overhang = 0; - fi.maxwidth = GetGlyphInfoSys(ctfont, 'W', synth && font.IsBold()).width; // TODO? - fi.avewidth = GetGlyphInfoSys(ctfont, 'e', synth && font.IsBold()).width; - fi.default_char = '?'; - fi.fixedpitch = CTFontGetSymbolicTraits(ctfont) & kCTFontMonoSpaceTrait; - fi.ttf = true; - - CFRef fd = CTFontCopyFontDescriptor(ctfont); - CFRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fd, kCTFontURLAttribute); - CFRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); - String p = ToString(path); - - if(p.GetCount() < 250) - strcpy(fi.path, ~p); - else - *fi.path = 0; - } - return fi; -} - -GlyphInfo GetGlyphInfoSys(Font font, int chr) -{ - LTIMING("GetGlyphInfoSys"); - bool synth; - CTFontRef ctfont = CT_Font(font, synth); - return GetGlyphInfoSys(ctfont, chr, synth && font.IsBold()); -} - -Vector GetAllFacesSys() -{ - Index facename; - - facename.Add("Arial"); // This is default GUI font, changed afterward - facename.Add("Times New Roman"); - facename.Add("Arial"); - facename.Add("Courier New"); - - int oi = facename.GetCount(); - - AutoreleasePool __; - - CFRef collection = CTFontCollectionCreateFromAvailableFonts(0); - if(collection) { - CFRef fonts = CTFontCollectionCreateMatchingFontDescriptors(collection); - if(fonts) { - int count = CFArrayGetCount(fonts); - for(int i = 0; i < count; ++i) { - CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i); - CFRef family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); - facename.FindAdd(ToString(family_name)); - } - } - } - - Vector h = facename.PickKeys(); - Sort(SubRange(h, oi, h.GetCount() - oi)); - - Vector r; - for(String s : h) { - FaceInfo& fi = r.Add(); - fi.name = s; - fi.info = Font::TTF; - CFRef fs = CFStringCreateWithCString(NULL, ~s, kCFStringEncodingUTF8); - CFRef ctfont = CTFontCreateWithName(fs, 12, NULL); - dword traits = CTFontGetSymbolicTraits(ctfont); - fi.info = Font::SCALEABLE; - if(traits & kCTFontMonoSpaceTrait) - fi.info |= Font::FIXEDPITCH; - switch(traits & kCTFontClassMaskTrait) { - case kCTFontOldStyleSerifsClass: - case kCTFontTransitionalSerifsClass: - case kCTFontModernSerifsClass: - case kCTFontClarendonSerifsClass: - case kCTFontSlabSerifsClass: - case kCTFontFreeformSerifsClass: - fi.info |= Font::SERIFSTYLE; - break; - case kCTFontScriptsClass: - fi.info |= Font::SCRIPTSTYLE; - break; - } - } - - return r; -} - -String GetFontDataSys(Font font) -{ - return LoadFile(font.Fi().path); -} - -struct sCGPathTarget { - double x, y; - FontGlyphConsumer *sw; -}; - -static void convertCGPathToQPainterPath(void *info, const CGPathElement *e) -{ - 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); - bool synth; - CTFontRef ctfont = CT_Font(font, synth); - CGGlyph glyph_index = GetCharGlyph(ctfont, chr); - CFRef cgpath = CTFontCreatePathForGlyph(ctfont, glyph_index, &cgMatrix); - sCGPathTarget t; - t.x = x; - t.y = y + font.GetAscent(); - t.sw = &sw; - CGPathApply(cgpath, &t, convertCGPathToQPainterPath); -} +CTFontRef CT_Font(Font fnt, bool& synth); // From Draw void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx) diff --git a/uppsrc/CtrlCore/CocoMM.h b/uppsrc/CtrlCore/CocoMM.h index 5cdb4ad2c..208fadbf3 100644 --- a/uppsrc/CtrlCore/CocoMM.h +++ b/uppsrc/CtrlCore/CocoMM.h @@ -43,6 +43,7 @@ CGImageRef createCGImage(const Image& img); NSImage *GetNSImage(const Image& img); +// From Draw/FontCoco.cpp WString ToWString(CFStringRef s); String ToString(CFStringRef s); diff --git a/uppsrc/CtrlCore/CocoUtil.mm b/uppsrc/CtrlCore/CocoUtil.mm deleted file mode 100644 index d3e180ff6..000000000 --- a/uppsrc/CtrlCore/CocoUtil.mm +++ /dev/null @@ -1,24 +0,0 @@ -#include "CocoMM.h" - -#ifdef PLATFORM_COCOA - -namespace Upp { - -WString ToWString(CFStringRef s) -{ - if(!s) return Null; - CFIndex l = CFStringGetLength(s); - if(!l) return Null; - WStringBuffer b(l); - CFStringGetCharacters(s, CFRangeMake(0, l), (UniChar *)~b); - return b; -} - -String ToString(CFStringRef s) -{ - return ToWString(s).ToString(); -} - -}; - -#endif diff --git a/uppsrc/CtrlCore/CtrlCore.upp b/uppsrc/CtrlCore/CtrlCore.upp index 73f336e9a..e7fed079f 100644 --- a/uppsrc/CtrlCore/CtrlCore.upp +++ b/uppsrc/CtrlCore/CtrlCore.upp @@ -10,8 +10,6 @@ library(WIN32) "advapi32 comdlg32 comctl32"; library(WIN32) "user32 gdi32"; -link(OSX !X11) "-framework Foundation -framework Cocoa -framework Carbon"; - pkg_config(POSIX) "freetype2 x11 xinerama xrender xft xdmcp fontconfig xcb xext"; pkg_config(POSIX !X11) "gtk+-3.0 libnotify"; @@ -110,7 +108,6 @@ file CocoAfter.h, CocoKeys.h, CocoMM.h, - CocoUtil.mm, CocoDraw.mm, CocoDrawOp.mm, CocoImage.mm, diff --git a/uppsrc/Draw/Draw.upp b/uppsrc/Draw/Draw.upp index 9b87d10a3..1fbd445ab 100644 --- a/uppsrc/Draw/Draw.upp +++ b/uppsrc/Draw/Draw.upp @@ -10,6 +10,8 @@ uses library(WIN32) "user32 gdi32"; +link(OSX !X11) "-framework Foundation -framework Cocoa -framework Carbon"; + pkg_config(POSIX) "freetype2 x11 fontconfig xcb expat"; file @@ -19,6 +21,7 @@ file FontCR.cpp, FontWin32.cpp, FontFc.cpp, + FontCoco.mm, Draw.cpp, DrawText.cpp, DrawData.cpp, diff --git a/uppsrc/Draw/FontCoco.mm b/uppsrc/Draw/FontCoco.mm new file mode 100644 index 000000000..0490a00fd --- /dev/null +++ b/uppsrc/Draw/FontCoco.mm @@ -0,0 +1,325 @@ +#include "Draw.h" + +#define LLOG(x) // LOG(x) +#define LTIMING(x) // TIMING(x) + +#if !defined(CUSTOM_FONTSYS) && defined(PLATFORM_COCOA) + +#define Point NS_Point +#define Rect NS_Rect +#define Size NS_Size +#include +#undef Point +#undef Rect +#undef Size + +namespace Upp { + +namespace Detail { // TODO: following utilities are normally defined in CtrlCore, rename to avoid name clash + +template +struct CFRef { + T ptr; + T operator~() { return ptr; } + operator T() { return ptr; } + T operator->() { return ptr; } + T Detach() { T h = ptr; ptr = NULL; return h; } + CFRef(T p) { ptr = p; } + ~CFRef() { if(ptr) CFRelease(ptr); } +}; + +struct AutoreleasePool { + NSAutoreleasePool *pool; + + AutoreleasePool() { + pool = [[NSAutoreleasePool alloc] init]; + } + ~AutoreleasePool() { + [pool release]; + } +}; + +}; + +using namespace Detail; + +WString ToWString(CFStringRef s) +{ + if(!s) return Null; + CFIndex l = CFStringGetLength(s); + if(!l) return Null; + WStringBuffer b(l); + CFStringGetCharacters(s, CFRangeMake(0, l), (UniChar *)~b); + return b; +} + +String ToString(CFStringRef s) +{ + return ToWString(s).ToString(); +} + +CTFontRef CT_Font0(Font fnt, bool& synth) +{ + CFRef s = CFStringCreateWithCString(NULL, ~fnt.GetFaceName(), kCFStringEncodingUTF8); + CFRef ctfont0 = CTFontCreateWithName(s, fnt.GetHeight(), NULL); + synth = false; + if(fnt.IsItalic() || fnt.IsBold()) { + CTFontSymbolicTraits t = 0; + if(fnt.IsBold()) + t |= kCTFontBoldTrait; + if(fnt.IsItalic()) + t |= kCTFontItalicTrait; + CFRef ctfont = CTFontCreateCopyWithSymbolicTraits(ctfont0, fnt.GetHeight(), + NULL, t, t); + if(ctfont) + return ctfont.Detach(); + synth = true; + } + return ctfont0.Detach(); +} + +CTFontRef CT_Font(Font fnt, bool& synth) +{ + struct Entry { + Font font; + CTFontRef ctfont = NULL; + bool synth = false; + + void Free() { if(ctfont) CFRelease(ctfont); ctfont = NULL; } + + Entry() { font.Height(-22222); } + ~Entry() { Free(); } + }; + + const int FONTCACHE = 64; + static Entry cache[FONTCACHE]; + for(int i = 0; i < FONTCACHE; i++) + if(cache[i].font == fnt) { + synth = cache[i].synth; + return cache[i].ctfont; + } + Entry& e = cache[Random(FONTCACHE)]; + e.Free(); + e.font = fnt; + e.ctfont = CT_Font0(fnt, synth); + e.synth = synth; + 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, bool bold_synth, CGRect *bounds = NULL) +{ + GlyphInfo gi; + gi.lspc = gi.rspc = 0; + gi.width = 0x8000; + if(ctfont) { + LTIMING("GetGlyphInfoSys 2"); + CGGlyph glyph_index = GetCharGlyph(ctfont, chr); + if(glyph_index) { + CGSize advance; + CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, &glyph_index, &advance, 1); + gi.width = ceil(advance.width); + gi.lspc = gi.rspc = 0; // TODO! (using bounding box?) + gi.glyphi = glyph_index; + if(bold_synth) + gi.width++; + if(bounds) + CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontOrientationHorizontal, + &glyph_index, bounds, 1); + + } + } + return gi; +} + +CommonFontInfo GetFontInfoSys(Font font) +{ + CommonFontInfo fi; + String path; + bool synth; + CTFontRef ctfont = CT_Font(font, synth); + if(ctfont) { + #if 0 + DDUMP(font); + DDUMP(CTFontGetSize(ctfont)); + DDUMP(CTFontGetAscent(ctfont)); + DDUMP(CTFontGetDescent(ctfont)); + DDUMP(); + DDUMP(CTFontGetXHeight(ctfont)); + DDUMP(CTFontGetUnderlinePosition(ctfont)); + DDUMP(MakeRect(CTFontGetBoundingBox(ctfont))); + DDUMPHEX(CTFontGetSymbolicTraits(ctfont)); + DDUMP(font); + CGRect cr = CTFontGetBoundingBox(ctfont); + DDUMP(cr.origin.y); + DDUMP(cr.size.height); + DDUMP(cr.origin.y + cr.size.height); + #endif + fi.descent = ceil(CTFontGetDescent(ctfont)); + fi.ascent = ceil(CTFontGetAscent(ctfont)); + fi.external = ceil(CTFontGetLeading(ctfont)); + + // Some MacOS fonts have really weird ascent/descents (namely stadard GUI font...) + // let us fix it by testing typical charactes bounding boxes + + static WString descent_test = "yjgp"; + CGRect bb; + for(int i = 0; i < descent_test.GetCount(); i++) + if(GetGlyphInfoSys(ctfont, descent_test[i], synth && font.IsBold(), &bb).IsNormal()) + fi.descent = max(fi.descent, (int)ceil(-bb.origin.y)); + + int ascent = fi.ascent; + static WString ascent_test = "ÀÁÂÃÄË"; + for(int i = 0; i < ascent_test.GetCount(); i++) + if(GetGlyphInfoSys(ctfont, ascent_test[i], synth && font.IsBold(), &bb).IsNormal()) + ascent = max(ascent, (int)ceil(bb.origin.y + bb.size.height)); + + fi.ascent = ascent; + + fi.internal = 0; + fi.overhang = 0; + fi.maxwidth = GetGlyphInfoSys(ctfont, 'W', synth && font.IsBold()).width; // TODO? + fi.avewidth = GetGlyphInfoSys(ctfont, 'e', synth && font.IsBold()).width; + fi.default_char = '?'; + fi.fixedpitch = CTFontGetSymbolicTraits(ctfont) & kCTFontMonoSpaceTrait; + fi.ttf = true; + + CFRef fd = CTFontCopyFontDescriptor(ctfont); + CFRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fd, kCTFontURLAttribute); + CFRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); + String p = ToString(path); + + if(p.GetCount() < 250) + strcpy(fi.path, ~p); + else + *fi.path = 0; + } + return fi; +} + +GlyphInfo GetGlyphInfoSys(Font font, int chr) +{ + LTIMING("GetGlyphInfoSys"); + bool synth; + CTFontRef ctfont = CT_Font(font, synth); + return GetGlyphInfoSys(ctfont, chr, synth && font.IsBold()); +} + +Vector GetAllFacesSys() +{ + Index facename; + + facename.Add("Arial"); // This is default GUI font, changed afterward + facename.Add("Times New Roman"); + facename.Add("Arial"); + facename.Add("Courier New"); + + int oi = facename.GetCount(); + + AutoreleasePool __; + + CFRef collection = CTFontCollectionCreateFromAvailableFonts(0); + if(collection) { + CFRef fonts = CTFontCollectionCreateMatchingFontDescriptors(collection); + if(fonts) { + int count = CFArrayGetCount(fonts); + for(int i = 0; i < count; ++i) { + CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i); + CFRef family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); + facename.FindAdd(ToString(family_name)); + } + } + } + + Vector h = facename.PickKeys(); + Sort(SubRange(h, oi, h.GetCount() - oi)); + + Vector r; + for(String s : h) { + FaceInfo& fi = r.Add(); + fi.name = s; + fi.info = Font::TTF; + CFRef fs = CFStringCreateWithCString(NULL, ~s, kCFStringEncodingUTF8); + CFRef ctfont = CTFontCreateWithName(fs, 12, NULL); + dword traits = CTFontGetSymbolicTraits(ctfont); + fi.info = Font::SCALEABLE; + if(traits & kCTFontMonoSpaceTrait) + fi.info |= Font::FIXEDPITCH; + switch(traits & kCTFontClassMaskTrait) { + case kCTFontOldStyleSerifsClass: + case kCTFontTransitionalSerifsClass: + case kCTFontModernSerifsClass: + case kCTFontClarendonSerifsClass: + case kCTFontSlabSerifsClass: + case kCTFontFreeformSerifsClass: + fi.info |= Font::SERIFSTYLE; + break; + case kCTFontScriptsClass: + fi.info |= Font::SCRIPTSTYLE; + break; + } + } + + return r; +} + +String GetFontDataSys(Font font) +{ + return LoadFile(font.Fi().path); +} + +struct sCGPathTarget { + double x, y; + FontGlyphConsumer *sw; +}; + +static void convertCGPathToQPainterPath(void *info, const CGPathElement *e) +{ + 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); + bool synth; + CTFontRef ctfont = CT_Font(font, synth); + CGGlyph glyph_index = GetCharGlyph(ctfont, chr); + CFRef cgpath = CTFontCreatePathForGlyph(ctfont, glyph_index, &cgMatrix); + sCGPathTarget t; + t.x = x; + t.y = y + font.GetAscent(); + t.sw = &sw; + CGPathApply(cgpath, &t, convertCGPathToQPainterPath); +} + +}; + +#endif \ No newline at end of file diff --git a/uppsrc/ide/OnlineSearch.cpp b/uppsrc/ide/OnlineSearch.cpp index d28f532f8..e9ffb2913 100644 --- a/uppsrc/ide/OnlineSearch.cpp +++ b/uppsrc/ide/OnlineSearch.cpp @@ -60,7 +60,7 @@ void SearchEnginesDefaultSetup() } struct IconDisplay : Display { - virtual Size GetStdSize(const Value&) { return DPI(16, 16); } + virtual Size GetStdSize(const Value&) const { return DPI(16, 16); } virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const { w.DrawRect(r, paper);