17 #include <Availability.h> 30 #ifdef MAC_OS_X_VERSION_10_11 38 const CTFontOrientation defaultFontOrientation = kCTFontDefaultOrientation;
39 const CTFontOrientation horizontalFontOrientation = kCTFontHorizontalOrientation;
40 const CTFontOrientation verticalFontOrientation = kCTFontVerticalOrientation;
49 if (
const TColor *
const color =
gROOT->GetColor(colorIndex)) {
50 color->GetRGB(r, g, b);
51 a = color->GetAlpha();
56 CGRect BBoxForCTRun(CTFontRef font, CTRunRef run)
58 assert(font != 0 &&
"BBoxForCTRun, parameter 'font' is null");
59 assert(run != 0 &&
"BBoxForCTRun, parameter 'run' is null");
62 if (
const CFIndex nGlyphs = CTRunGetGlyphCount(run)) {
63 std::vector<CGGlyph> glyphs(nGlyphs);
64 CTRunGetGlyphs(run, CFRangeMake(0, 0), &glyphs[0]);
65 bbox = CTFontGetBoundingRectsForGlyphs(font, defaultFontOrientation,
66 &glyphs[0], 0, nGlyphs);
80 CFStringRef keys[] = {kCTFontAttributeName};
81 CFTypeRef values[] = {font};
83 Init(textLine, 1, keys, values);
93 CFStringRef keys[] = {kCTFontAttributeName};
94 CFTypeRef values[] = {font};
96 Init(unichars, 1, keys, values);
107 const CFScopeGuard<CGColorSpaceRef> rgbColorSpace(CGColorSpaceCreateDeviceRGB());
108 if (!rgbColorSpace.Get())
109 throw std::runtime_error(
"TextLine: color space");
111 Float_t rgba[] = {0.f, 0.f, 0.f, 1.f};
112 GetTextColorForIndex(color, rgba[0], rgba[1], rgba[2], rgba[3]);
113 const CGFloat cgRgba[] = {rgba[0], rgba[1], rgba[2], rgba[3]};
115 const CFScopeGuard<CGColorRef> textColor(CGColorCreate(rgbColorSpace.Get(), cgRgba));
118 CFStringRef keys[] = {kCTFontAttributeName, kCTForegroundColorAttributeName};
119 CFTypeRef values[] = {font, textColor.Get()};
121 Init(textLine, 2, keys, values);
131 CFScopeGuard<CGColorSpaceRef> rgbColorSpace(CGColorSpaceCreateDeviceRGB());
133 if (!rgbColorSpace.Get())
134 throw std::runtime_error(
"TexLine: color space is null");
136 CFScopeGuard<CGColorRef> textColor(CGColorCreate(rgbColorSpace.Get(), rgb));
139 CFStringRef keys[] = {kCTFontAttributeName, kCTForegroundColorAttributeName};
140 CFTypeRef values[] = {font, textColor.Get()};
142 Init(textLine, 2, keys, values);
153 const CFScopeGuard<CGColorSpaceRef> rgbColorSpace(CGColorSpaceCreateDeviceRGB());
154 if (!rgbColorSpace.Get())
155 throw std::runtime_error(
"TextLine: color space");
157 Float_t rgba[] = {0.f, 0.f, 0.f, 1.f};
158 GetTextColorForIndex(color, rgba[0], rgba[1], rgba[2], rgba[3]);
159 const CGFloat cgRgba[] = {rgba[0], rgba[1], rgba[2], rgba[3]};
161 const CFScopeGuard<CGColorRef> textColor(CGColorCreate(rgbColorSpace.Get(), cgRgba));
164 CFStringRef keys[] = {kCTFontAttributeName, kCTForegroundColorAttributeName};
165 CFTypeRef values[] = {font, textColor.Get()};
167 Init(unichars, 2, keys, values);
182 CGFloat ascent = 0., descent = 0., leading = 0.;
183 w =
UInt_t(CTLineGetTypographicBounds(
fCTLine, &ascent, &descent, &leading));
192 CGFloat ascent = 0., descent = 0., leading = 0.;
193 CTLineGetTypographicBounds(
fCTLine, &ascent, &descent, &leading);
195 desc =
Int_t(descent);
199 CFArrayRef runs = CTLineGetGlyphRuns(
fCTLine);
200 if (runs && CFArrayGetCount(runs) &&
fCTFont) {
201 CTRunRef firstRun =
static_cast<CTRunRef
>(CFArrayGetValueAtIndex(runs, 0));
203 if (CGRectIsNull(box))
206 for (CFIndex i = 1,
e = CFArrayGetCount(runs); i <
e; ++i) {
207 CTRunRef run =
static_cast<CTRunRef
>(CFArrayGetValueAtIndex(runs, i));
208 CGRect nextBox = BBoxForCTRun(
fCTFont, run);
209 if (CGRectIsNull(nextBox))
211 box = CGRectUnion(box, nextBox);
226 const CFScopeGuard<CFDictionaryRef> stringAttribs(CFDictionaryCreate(kCFAllocatorDefault, (
const void **)keys, (
const void **)values,
227 nAttribs, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
228 if (!stringAttribs.Get())
229 throw std::runtime_error(
"TextLine: null attribs");
231 const CFScopeGuard<CFStringRef> wrappedCString(CFStringCreateWithCString(kCFAllocatorDefault, textLine, kCFStringEncodingMacRoman));
232 if (!wrappedCString.Get())
233 throw std::runtime_error(
"TextLine: cstr wrapper");
235 CFScopeGuard<CFAttributedStringRef> attributedString(CFAttributedStringCreate(kCFAllocatorDefault,
236 wrappedCString.Get(), stringAttribs.Get()));
237 fCTLine = CTLineCreateWithAttributedString(attributedString.Get());
240 throw std::runtime_error(
"TextLine: attrib string");
244 void TextLine::Init(
const std::vector<UniChar> &unichars,
UInt_t nAttribs, CFStringRef *keys, CFTypeRef *values)
248 const CFScopeGuard<CFStringRef> wrappedUniString(CFStringCreateWithCharacters(kCFAllocatorDefault, &unichars[0], unichars.size()));
249 const CFScopeGuard<CFDictionaryRef> stringAttribs(CFDictionaryCreate(kCFAllocatorDefault, (
const void **)keys, (
const void **)values,
250 nAttribs, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
252 if (!stringAttribs.Get())
253 throw std::runtime_error(
"TextLine: null attribs");
255 if (!wrappedUniString.Get())
256 throw std::runtime_error(
"TextLine: cstr wrapper");
258 const CFScopeGuard<CFAttributedStringRef> attributedString(CFAttributedStringCreate(kCFAllocatorDefault,
259 wrappedUniString.Get(), stringAttribs.Get()));
260 fCTLine = CTLineCreateWithAttributedString(attributedString.Get());
263 throw std::runtime_error(
"TextLine: attrib string");
269 assert(ctx != 0 &&
"DrawLine, ctx parameter is null");
277 assert(ctx != 0 &&
"DrawLine, ctx parameter is null");
279 CGContextSetAllowsAntialiasing(ctx, 1);
309 CGContextSetTextPosition(ctx, 0., 0.);
310 CGContextTranslateCTM(ctx, x, y);
312 CGContextTranslateCTM(ctx, xc, yc);
313 CGContextTranslateCTM(ctx, -0.5 * w, -0.5 *
h);
321 typedef std::vector<CGSize>::size_type size_type;
326 assert(ctx != 0 &&
"DrawTextLineNoKerning, ctx parameter is null");
327 assert(font != 0 &&
"DrawTextLineNoKerning, font parameter is null");
328 assert(text.size() &&
"DrawTextLineNoKerning, text parameter is an empty vector");
330 std::vector<CGGlyph> glyphs(text.size());
331 if (!CTFontGetGlyphsForCharacters(font, &text[0], &glyphs[0], text.size())) {
332 ::Error(
"DrawTextLineNoKerning",
"Font could not encode all Unicode characters in a text");
336 std::vector<CGSize> glyphAdvances(glyphs.size());
337 CTFontGetAdvancesForGlyphs(font, horizontalFontOrientation, &glyphs[0], &glyphAdvances[0], glyphs.size());
339 CGFloat currentX =
x;
340 std::vector<CGPoint> glyphPositions(glyphs.size());
341 glyphPositions[0].x = currentX;
342 glyphPositions[0].y =
y;
344 for (size_type i = 1; i < glyphs.size(); ++i) {
345 currentX +=
std::ceil(glyphAdvances[i - 1].width);
346 glyphPositions[i].x = currentX;
347 glyphPositions[i].y =
y;
350 CTFontDrawGlyphs(font, &glyphs[0], &glyphPositions[0], glyphs.size(), ctx);
void GetAscentDescent(Int_t &asc, Int_t &desc) const
Double_t Floor(Double_t x)
void GetBounds(UInt_t &w, UInt_t &h) const
Namespace for new ROOT classes and functions.
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
const CTFontOrientation horizontalFontOrientation
constexpr Double_t DegToRad()
const CTFontOrientation defaultFontOrientation
TextLine(const char *textLine, CTFontRef font)
const CTFontOrientation verticalFontOrientation
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
The color creation and management class.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Double_t Ceil(Double_t x)
void DrawLine(CGContextRef ctx) const
void DrawTextLineNoKerning(CGContextRef ctx, CTFontRef font, const std::vector< UniChar > &text, Int_t x, Int_t y)
void Init(const char *textLine, UInt_t nAttribs, CFStringRef *keys, CFTypeRef *values)
void Error(ErrorHandler_t func, int code, const char *va_(fmt),...)
Write error message and call a handler, if required.
static constexpr double g