201 {
203 if (!fontRuns.atEnd()) {
204 fontRuns.consume();
205 font = fontRuns.currentFont();
206 }
208
209 SkUniqueCFRef<CFStringRef> textString(
210 CFStringCreateWithBytes(kCFAllocatorDefault, (const uint8_t*)utf8, utf8Bytes,
211 kCFStringEncodingUTF8, false));
212
213 UTF16ToUTF8IndicesMap utf8IndicesMap;
214 if (!utf8IndicesMap.setUTF8(utf8, utf8Bytes)) {
215 return;
216 }
217
219
220 SkUniqueCFRef<CFMutableDictionaryRef> attr(
221 CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
222 &kCFTypeDictionaryKeyCallBacks,
223 &kCFTypeDictionaryValueCallBacks));
224 CFDictionaryAddValue(attr.get(), kCTFontAttributeName, ctfont.get());
225 if ((false)) {
226
229 }
230
231 SkUniqueCFRef<CFAttributedStringRef> attrString(
232 CFAttributedStringCreate(kCFAllocatorDefault, textString.get(), attr.get()));
233
234 SkUniqueCFRef<CTTypesetterRef> typesetter(
235 CTTypesetterCreateWithAttributedString(attrString.get()));
236
237
238
239 std::vector<SkFont> fontStorage;
240 std::vector<SkShaper::RunHandler::RunInfo> infos;
241
243 while (SkUniqueCFRef<CTLineRef> line = iter.nextLine()) {
244 CFArrayRef run_array = CTLineGetGlyphRuns(
line.get());
245 CFIndex runCount = CFArrayGetCount(run_array);
246 if (runCount == 0) {
247 continue;
248 }
249 handler->beginLine();
250 fontStorage.clear();
251 fontStorage.reserve(runCount);
252 infos.clear();
253 for (CFIndex j = 0; j < runCount; ++j) {
254 CTRunRef
run = (CTRunRef)CFArrayGetValueAtIndex(run_array, j);
255 CFIndex runGlyphs = CTRunGetGlyphCount(
run);
256
257 SkASSERT(
sizeof(CGGlyph) ==
sizeof(uint16_t));
258
260 CTRunGetAdvances(
run, {0, runGlyphs}, advances.data());
262 for (CFIndex k = 0; k < runGlyphs; ++k) {
263 adv += advances[k].width;
264 }
265
266 CFRange cfRange = CTRunGetStringRange(
run);
267 auto range = utf8IndicesMap.mapRange(cfRange.location, cfRange.length);
268
270 infos.push_back({
271 fontStorage.back(),
272 0,
273 {adv, 0},
274 (size_t)runGlyphs,
275 {range.first, range.second},
276 });
277 handler->runInfo(infos.back());
278 }
279 handler->commitRunInfo();
280
281
283 for (CFIndex j = 0; j < runCount; ++j) {
284 const auto&
info = infos[j];
286
287 CTRunRef
run = (CTRunRef)CFArrayGetValueAtIndex(run_array, j);
288 CFIndex runGlyphs =
info.glyphCount;
290
291 CTRunGetGlyphs(
run, {0, runGlyphs},
buffer.glyphs);
292
294 CTRunGetPositions(
run, {0, runGlyphs}, positions.data());
297 indices.
reset(runGlyphs);
298 CTRunGetStringIndices(
run, {0, runGlyphs}, indices.
data());
299 }
300
301 for (CFIndex k = 0; k < runGlyphs; ++k) {
303 buffer.point.fX + SkScalarFromCGFloat(positions[k].
x) - lineAdvance,
305 };
307 buffer.offsets[k] = {0, 0};
308 }
310 buffer.clusters[k] = utf8IndicesMap.mapIndex(indices[k]);
311 }
312 }
313 handler->commitRunBuffer(
info);
314 lineAdvance +=
info.fAdvance.fX;
315 }
316 handler->commitLine();
317 }
318}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static void dict_add_double(CFMutableDictionaryRef d, const void *name, double value)
static SkUniqueCFRef< CTFontRef > create_ctfont_from_font(const SkFont &font)
const CFStringRef kCTTracking_AttributeName
static SkFont run_to_font(CTRunRef run, const SkFont &orig)
static const uint8_t buffer[]
font
Font Metadata and Metrics.