More work.
This commit is contained in:
parent
bab798543f
commit
f147edf949
|
@ -18,6 +18,7 @@ list(APPEND _LIBUI_SOURCES
|
|||
darwin/editablecombo.m
|
||||
darwin/entry.m
|
||||
darwin/fontbutton.m
|
||||
darwin/fontmatch.m
|
||||
darwin/form.m
|
||||
darwin/graphemes.m
|
||||
darwin/grid.m
|
||||
|
|
|
@ -292,38 +292,6 @@ struct framesetter {
|
|||
CGSize extents;
|
||||
};
|
||||
|
||||
// TODO CTFrameProgression for RTL/LTR
|
||||
// TODO kCTParagraphStyleSpecifierMaximumLineSpacing, kCTParagraphStyleSpecifierMinimumLineSpacing, kCTParagraphStyleSpecifierLineSpacingAdjustment for line spacing
|
||||
static void mkFramesetter(uiDrawTextLayout *layout, struct framesetter *fs)
|
||||
{
|
||||
CFRange fitRange;
|
||||
CGFloat width;
|
||||
|
||||
fs->fs = CTFramesetterCreateWithAttributedString(layout->mas);
|
||||
if (fs->fs == NULL)
|
||||
complain("error creating CTFramesetter object in mkFramesetter()");
|
||||
|
||||
// TODO kCTFramePathWidthAttributeName?
|
||||
fs->frameAttrib = NULL;
|
||||
|
||||
width = layout->width;
|
||||
if (layout->width < 0)
|
||||
width = CGFLOAT_MAX;
|
||||
// TODO these seem to be floor()'d or truncated?
|
||||
fs->extents = CTFramesetterSuggestFrameSizeWithConstraints(fs->fs,
|
||||
CFRangeMake(0, 0),
|
||||
fs->frameAttrib,
|
||||
CGSizeMake(width, CGFLOAT_MAX),
|
||||
&fitRange); // not documented as accepting NULL
|
||||
}
|
||||
|
||||
static void freeFramesetter(struct framesetter *fs)
|
||||
{
|
||||
if (fs->frameAttrib != NULL)
|
||||
CFRelease(fs->frameAttrib);
|
||||
CFRelease(fs->fs);
|
||||
}
|
||||
|
||||
// LONGTERM allow line separation and leading to be factored into a wrapping text layout
|
||||
|
||||
// TODO reconcile differences in character wrapping on platforms
|
||||
|
|
|
@ -4,123 +4,18 @@
|
|||
struct uiDrawTextLayout {
|
||||
CFAttributedStringRef attrstr;
|
||||
double width;
|
||||
CTFramesetterRef framesetter;
|
||||
CGSize size;
|
||||
CGPathRef path;
|
||||
};
|
||||
|
||||
// since uiDrawTextWeight effectively corresponds to OS/2 weights (which roughly correspond to GDI, Pango, and DirectWrite weights, and to a lesser(? TODO) degree, CSS weights), let's just do what Core Text does with OS/2 weights
|
||||
// TODO this will not be correct for system fonts, which use cached values that have no relation to the OS/2 weights; we need to figure out how to reconcile these
|
||||
// for more information, see https://bugzilla.gnome.org/show_bug.cgi?id=766148 and TODO_put_blog_post_here_once_I_write_it (TODO keep this line when resolving the above TODO)
|
||||
static const double weightsToCTWeights[] = {
|
||||
-1.0, // 0..99
|
||||
-0.7, // 100..199
|
||||
-0.5, // 200..299
|
||||
-0.23, // 300..399
|
||||
0.0, // 400..499
|
||||
0.2, // 500..599
|
||||
0.3, // 600..699
|
||||
0.4, // 700..799
|
||||
0.6, // 800..899
|
||||
0.8, // 900..999
|
||||
1.0, // 1000
|
||||
};
|
||||
|
||||
static double weightToCTWeight(uiDrawTextWeight weight)
|
||||
{
|
||||
int weightClass;
|
||||
double ctclass;
|
||||
double rest, weightFloor, nextFloor;
|
||||
|
||||
if (weight <= 0)
|
||||
return -1.0;
|
||||
if (weight >= 1000)
|
||||
return 1.0;
|
||||
|
||||
weightClass = weight / 100;
|
||||
rest = (double) weight;
|
||||
weightFloor = (double) (weightClass * 100);
|
||||
nextFloor = (double) ((weightClass + 1) * 100);
|
||||
rest = (rest - weightFloor) / (nextFloor - weightFloor);
|
||||
|
||||
ctclass = weightsToCTWeights[weightClass];
|
||||
return fma(rest,
|
||||
weightsToCTWeights[weightClass + 1] - ctclass,
|
||||
ctclass);
|
||||
}
|
||||
|
||||
// TODO put italics here
|
||||
|
||||
// based on what Core Text says about actual fonts (system fonts, system fonts in another folder to avoid using cached values, Adobe Font Folio 11, Google Fonts archive, fonts in Windows 7/8.1/10)
|
||||
static const double stretchesToCTWidths[] = {
|
||||
[uiDrawTextStretchUltraCondensed] = -0.400000,
|
||||
[uiDrawTextStretchExtraCondensed] = -0.300000,
|
||||
[uiDrawTextStretchCondensed] = -0.200000,
|
||||
[uiDrawTextStretchSemiCondensed] = -0.100000,
|
||||
[uiDrawTextStretchNormal] = 0.000000,
|
||||
[uiDrawTextStretchSemiExpanded] = 0.100000,
|
||||
[uiDrawTextStretchExpanded] = 0.200000,
|
||||
[uiDrawTextStretchExtraExpanded] = 0.300000,
|
||||
// this one isn't present in any of the fonts I tested, but it follows naturally from the pattern of the rest, so... (TODO verify by checking the font files directly)
|
||||
[uiDrawTextStretchUltraExpanded] = 0.400000,
|
||||
};
|
||||
|
||||
static CFDictionaryRef fontdescToTraits(uiDrawFontDescriptor *fd)
|
||||
{
|
||||
CFMutableDictionaryRef traits;
|
||||
CFNumberRef num;
|
||||
double x;
|
||||
|
||||
traits = CFDictionaryCreateMutable(NULL, 2,
|
||||
// TODO are these correct?
|
||||
&kCFCopyStringDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
if (traits == NULL) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
x = weightToCTWeight(fd->Weight);
|
||||
num = CFNumberCreate(NULL, kCFNumberDoubleType, &x);
|
||||
CFDictionaryAddValue(traits, kCTFontWeightTrait, num);
|
||||
CFRelease(num);
|
||||
|
||||
// TODO italics
|
||||
|
||||
x = stretchesToCTWidths[fd->Stretch];
|
||||
num = CFNumberCreate(NULL, kCFNumberDoubleType, &x);
|
||||
CFDictionaryAddValue(traits, kCTFontWidthTrait, num);
|
||||
CFRelease(num);
|
||||
|
||||
return traits;
|
||||
}
|
||||
|
||||
static CTFontRef fontdescToCTFont(uiDrawFontDescriptor *fd)
|
||||
{
|
||||
CFMutableDictionaryRef attrs;
|
||||
CFStringRef cffamily;
|
||||
CFDictionaryRef traits;
|
||||
CTFontDescriptorRef desc;
|
||||
CTFontRef font;
|
||||
|
||||
attrs = CFDictionaryCreateMutable(NULL, 2,
|
||||
// TODO are these correct?
|
||||
&kCFCopyStringDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
if (attrs == NULL) {
|
||||
// TODO
|
||||
}
|
||||
cffamily = CFStringCreateWithCString(NULL, fd.Family, kCFStringEncodingUTF8);
|
||||
if (cffamily == NULL) {
|
||||
// TODO
|
||||
}
|
||||
CFDictionaryAddValue(attrs, kCTFontFamilyNameAttribute, cffamily);
|
||||
CFRelease(cffamily);
|
||||
traits = fontdescToTraits(fd);
|
||||
CFDictionaryAddValue(attrs, kCTFontTraitsAttribute, traits);
|
||||
CFRelease(traits);
|
||||
|
||||
desc = CTFontDescriptorCreateWithAttributes(attrs);
|
||||
CFRelease(attrs); // TODO correct?
|
||||
// This function DOES return a font with the closest traits that are available, so we don't have to do any manual matching.
|
||||
// TODO figure out why we had to for other things...
|
||||
font = CTFontCreateWithFontDescriptor(desc, fd.Size, NULL);
|
||||
desc = fontdescToCTFontDescriptor(fd);
|
||||
font = CTFontCreateWithFontDescriptor(desc, fd->Size, NULL);
|
||||
CFRelease(desc); // TODO correct?
|
||||
return font;
|
||||
}
|
||||
|
@ -165,10 +60,46 @@ static CFAttributedStringRef attrstrToCoreFoundation(uiAttributedString *s, uiDr
|
|||
|
||||
uiDrawTextLayout *uiDrawNewTextLayout(uiAttributedString *s, uiDrawFontDescriptor *defaultFont, double width)
|
||||
{
|
||||
uiDrawTextLayout *tl;
|
||||
CGFloat cgwidth;
|
||||
CFRange range, unused;
|
||||
CGRect rect;
|
||||
|
||||
tl = uiNew(uiDrawTextLayout);
|
||||
tl->attrstr = attrstrToCoreFoundation(s, defaultFont);
|
||||
range.location = 0;
|
||||
range.length = CFAttributedStringGetLength(tl->attrstr);
|
||||
tl->width = width;
|
||||
|
||||
// TODO CTFrameProgression for RTL/LTR
|
||||
// TODO kCTParagraphStyleSpecifierMaximumLineSpacing, kCTParagraphStyleSpecifierMinimumLineSpacing, kCTParagraphStyleSpecifierLineSpacingAdjustment for line spacing
|
||||
tl->framesetter = CTFramesetterCreateWithAttributedString(tl->attrstr);
|
||||
if (tl->framesetter == NULL) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
cgwidth = (CGFloat) width;
|
||||
if (cgwidth < 0)
|
||||
cgwidth = CGFLOAT_MAX;
|
||||
// TODO these seem to be floor()'d or truncated?
|
||||
// TODO double check to make sure this TODO was right
|
||||
tl->size = CTFramesetterSuggestFrameSizeWithConstraints(tl->framesetter,
|
||||
range,
|
||||
// TODO kCTFramePathWidthAttributeName?
|
||||
NULL,
|
||||
CGSizeMake(cgwidth, CGFLOAT_MAX),
|
||||
&unused); // not documented as accepting NULL
|
||||
|
||||
rect.origin = CGZeroPoint;
|
||||
rect.size = tl->size;
|
||||
tl->path = CGPathCreateWithRect(rect, NULL);
|
||||
return tl;
|
||||
}
|
||||
|
||||
void uiDrawFreeTextLayout(uiDrawTextLayout *tl)
|
||||
{
|
||||
CFRelease(tl->path);
|
||||
CFRelease(tl->framesetter);
|
||||
CFRelease(tl->attrstr);
|
||||
uiFree(tl);
|
||||
}
|
||||
|
|
|
@ -221,3 +221,35 @@ static const double stretchesToCTWidths[] = {
|
|||
// this one isn't present in any of the fonts I tested, but it follows naturally from the pattern of the rest, so... (TODO verify by checking the font files directly)
|
||||
[uiDrawTextStretchUltraExpanded] = 0.400000,
|
||||
};
|
||||
|
||||
CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd)
|
||||
{
|
||||
CFMutableDictionaryRef attrs;
|
||||
CFStringRef cffamily;
|
||||
CFNumberRef cfsize;
|
||||
CTFontDescriptorRef basedesc;
|
||||
|
||||
attrs = CFDictionaryCreateMutable(NULL, 2,
|
||||
// TODO are these correct?
|
||||
&kCFCopyStringDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
if (attrs == NULL) {
|
||||
// TODO
|
||||
}
|
||||
cffamily = CFStringCreateWithCString(NULL, fd->Family, kCFStringEncodingUTF8);
|
||||
if (cffamily == NULL) {
|
||||
// TODO
|
||||
}
|
||||
CFDictionaryAddValue(attrs, kCTFontFamilyNameAttribute, cffamily);
|
||||
CFRelease(cffamily);
|
||||
cfsize = CFNumberCreate(NULL, kCFNumberDoubleType, &(fd->Size));
|
||||
CFDictionaryAddValue(attrs, kCTFontSizeAttribute, cfsize);
|
||||
CFRelease(cfsize);
|
||||
|
||||
basedesc = CTFontDescriptorCreateWithAttributes(attrs);
|
||||
CFRelease(attrs); // TODO correct?
|
||||
return matchTraits(basedesc,
|
||||
weightToCTWeight(fd->Weight),
|
||||
fd->Italic,
|
||||
stretchesToCTWidths[fd->Stretch]);
|
||||
}
|
||||
|
|
|
@ -108,11 +108,6 @@ extern BOOL keycodeModifier(unsigned short keycode, uiModifiers *mod);
|
|||
extern uiDrawContext *newContext(CGContextRef, CGFloat);
|
||||
extern void freeContext(uiDrawContext *);
|
||||
|
||||
// drawtext.m
|
||||
extern uiDrawTextFont *mkTextFont(CTFontRef f, BOOL retain);
|
||||
extern uiDrawTextFont *mkTextFontFromNSFont(NSFont *f);
|
||||
extern void doDrawText(CGContextRef c, CGFloat cheight, double x, double y, uiDrawTextLayout *layout);
|
||||
|
||||
// fontbutton.m
|
||||
extern BOOL fontButtonInhibitSendAction(SEL sel, id from, id to);
|
||||
extern BOOL fontButtonOverrideTargetForAction(SEL sel, id from, id to, id *override);
|
||||
|
@ -144,3 +139,6 @@ extern NSImage *imageImage(uiImage *);
|
|||
// winmoveresize.m
|
||||
extern void doManualMove(NSWindow *w, NSEvent *initialEvent);
|
||||
extern void doManualResize(NSWindow *w, NSEvent *initialEvent, uiWindowResizeEdge edge);
|
||||
|
||||
// fontmatch.m
|
||||
extern CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd);
|
||||
|
|
Loading…
Reference in New Issue