361 {
362 if (graphemes) graphemes->clear();
363
364
365
367 return false;
368 }
369
370
371 const char32 kDottedCircleGlyph = 9676;
372 bool bad_glyph = false;
373 PangoFontMap* font_map = pango_cairo_font_map_get_default();
374 PangoContext* context = pango_context_new();
375 pango_context_set_font_map(context, font_map);
376 PangoLayout* layout;
377 {
378
380 layout = pango_layout_new(context);
381 }
382 if (desc_) {
383 pango_layout_set_font_description(layout, desc_);
384 } else {
385 PangoFontDescription *desc = pango_font_description_from_string(
387 pango_layout_set_font_description(layout, desc);
388 pango_font_description_free(desc);
389 }
390 pango_layout_set_text(layout, utf8_word, len);
391 PangoLayoutIter* run_iter = nullptr;
392 {
394 run_iter = pango_layout_get_iter(layout);
395 }
396 do {
397 PangoLayoutRun* run = pango_layout_iter_get_run_readonly(run_iter);
398 if (!run) {
399 tlog(2,
"Found end of line nullptr run marker\n");
400 continue;
401 }
402 PangoGlyph dotted_circle_glyph;
403 PangoFont* font = run->item->analysis.font;
404
405#ifdef _WIN32
406 PangoGlyphString* glyphs = pango_glyph_string_new();
407 const char s[] = "\xc2\xa7";
408 pango_shape(s, strlen(s), &(run->item->analysis), glyphs);
409 dotted_circle_glyph = glyphs->glyphs[0].glyph;
410#else
411 dotted_circle_glyph = pango_fc_font_get_glyph(
412 reinterpret_cast<PangoFcFont*>(font), kDottedCircleGlyph);
413#endif
414
416 PangoFontDescription* desc = pango_font_describe(font);
417 char* desc_str = pango_font_description_to_string(desc);
418 tlog(2,
"Desc of font in run: %s\n", desc_str);
419 g_free(desc_str);
420 pango_font_description_free(desc);
421 }
422
423 PangoGlyphItemIter cluster_iter;
424 gboolean have_cluster;
425 for (have_cluster = pango_glyph_item_iter_init_start(&cluster_iter,
426 run, utf8_word);
427 have_cluster && !bad_glyph;
428 have_cluster = pango_glyph_item_iter_next_cluster(&cluster_iter)) {
429 const int start_byte_index = cluster_iter.start_index;
430 const int end_byte_index = cluster_iter.end_index;
431 int start_glyph_index = cluster_iter.start_glyph;
432 int end_glyph_index = cluster_iter.end_glyph;
433 std::string cluster_text = std::string(utf8_word + start_byte_index,
434 end_byte_index - start_byte_index);
435 if (graphemes) graphemes->push_back(cluster_text);
437 tlog(2,
"Skipping whitespace\n");
438 continue;
439 }
441 printf("start_byte=%d end_byte=%d start_glyph=%d end_glyph=%d ",
442 start_byte_index, end_byte_index,
443 start_glyph_index, end_glyph_index);
444 }
445 for (int i = start_glyph_index,
446 step = (end_glyph_index > start_glyph_index) ? 1 : -1;
447 !bad_glyph && i != end_glyph_index; i+= step) {
448 const bool unknown_glyph =
449 (cluster_iter.glyph_item->glyphs->glyphs[i].glyph &
450 PANGO_GLYPH_UNKNOWN_FLAG);
451 const bool illegal_glyph =
452 (cluster_iter.glyph_item->glyphs->glyphs[i].glyph ==
453 dotted_circle_glyph);
454 bad_glyph = unknown_glyph || illegal_glyph;
456 printf("(%d=%d)", cluster_iter.glyph_item->glyphs->glyphs[i].glyph,
457 bad_glyph ? 1 : 0);
458 }
459 }
461 printf(" '%s'\n", cluster_text.c_str());
462 }
463 if (bad_glyph)
464 tlog(1,
"Found illegal glyph!\n");
465 }
466#ifdef _WIN32
467 pango_glyph_string_free(glyphs);
468#endif
469 } while (!bad_glyph && pango_layout_iter_next_run(run_iter));
470
471 pango_layout_iter_free(run_iter);
472 g_object_unref(context);
473 g_object_unref(layout);
474 if (bad_glyph && graphemes) graphemes->clear();
475 return !bad_glyph;
476}
#define TLOG_IS_ON(level)
#define DISABLE_HEAP_LEAK_CHECK
bool IsUTF8Whitespace(const char *text)
bool CoversUTF8Text(const char *utf8_text, int byte_length) const
std::string DescriptionName() const