Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ふりがな Deep Dive try! Swift Tokyo 2026

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.
Avatar for watura watura
April 14, 2026

ふりがな Deep Dive try! Swift Tokyo 2026

ふりがな Deep Dive
try! Swift Tokyo 2026
Apr 13 2026

Avatar for watura

watura

April 14, 2026

More Decks by watura

Other Decks in Programming

Transcript

  1. Ruby is a small-sized, supplementary text attached to a character

    or a group of characters in the main text. A run of ruby text, usually attached to the right of the characters in vertical writing mode or immediately above them in horizontal writing mode, indicates the reading or the meaning of those characters (see Figure 105). The characters in the main text that are annotated by ruby are called "base characters". Mainly Hiragana (cl-15) characters are often used for ruby to indicate how to read ideographic characters (cl-19); this is known as ruby annotation or as "furigana".
  2. f u n c C TR u byAnn o ta

    tionCr ea t eW ithAt tr ibu t es ( _ a l ign m en t : C TR u by Align m ent , // De f au l t A l ig n m e nt _ o v e r h an g : C TR u b y O ve r h an g , / / A lig n m e nt f o r lo ng e r f u r ig an a _ p o si t i on : C TR u byPo si t i on , / / Furi g an a P o s i t ion _ s t r ing : C F S t r ing , _ a t tr ib u t es : C F Di c tio n a ry ) -> C TR u byAnn o ta tion There are options that meets the Furigana requirements.
  3. let pairs: [(String, String)] = [ ("ੈքத", "All over the

    world"), ("͔Β", ""), ("։ൃऀ", "developers"), ("͕", ""), ("ू", "ͭͲ"), ("͍·͢ɻ", "") ] func ruby(_ base: String, _ ruby: String) -> NSAttributedString { let annotation = CTRubyAnnotationCreateWithAttributes( .auto, .auto, .before, ruby as CFString, [kCTRubyAnnotationSizeFactorAttributeName: 0.5] as CFDictionary ) return NSAttributedString( string: base, attributes: [ kCTRubyAnnotationAttributeName as NSAttributedString.Key: annotation ] ) }
  4. s tr uct Ru by A t tr ibu te:

    T e x tA t tr ib u te { l e t f u llR e a d i ng : S t r ing } s tr uct Ru byTe xtRe nd e re r : T e xt Re nd e re r { f u n c dr aw ( la yo ut : T e x t . La yo ut , i n ctx: in o ut G ra p h i cs C o n t e xt ) { f o r l i ne i n la yo u t { ctx.dr aw (l ine ) } } } l e t text = T e xt ("ੈքத") . c u s t o m At tr i bu te( Ru by At tr i bu te( f u llRe a d i ng : "A l l o v e r t he wo rl d") ) + T e xt ("͔Β") + T e xt ("։ൃऀ") . c u s t o m At tr i bu te( Ru by At tr i bu te( f u llRe a d i ng : " d ev e l o p er ") ) + T e xt ("͕") + T e xt ("ू") . c u s t o m At tr i bu te( Ru by At tr i bu te( f u llRe a d i ng : "ͭͲ") ) + T e xt ("͍·͢ɻʣ tex t . text Re nd e re r ( Ru byTe xtRe nd e re r ())
  5. ू ͭͲ Small Text above base characters ։ൃऀ developer Center

    alignment (Furigana < Base) All over the world Center alignment (Furigana > Base) ͔Β ੈքதO O
  6. ू ͭͲ Small Text above base characters ։ൃऀ developer Center

    alignment (Furigana < Base) fu n c dr aw ( la yo ut : T e xt . La yo ut , i n c o n t e xt : i n o u t G ra p h i cs C on t ex t ) { }
  7. ू ͭͲ Small Text above base characters ։ൃऀ developer Center

    alignment (Furigana < Base) fu n c dr aw ( la yo ut : T e xt . La yo ut , i n c o n t e xt : i n o u t G ra p h i cs C on t ex t ) { // 1. Mo v e c o n t ext f o r bi g g e r l in e H e i g ht var s hi f ted = c o n t e xt shi f t ed .t ra n s lat e B y (x: 0, y: l ine H e i gh t ) }
  8. ू ͭͲ Small Text above base characters ։ൃऀ developer Center

    alignment (Furigana < Base) fu n c dr aw ( la yo ut : T e xt . La yo ut , i n c o n t e xt : i n o u t G ra p h i cs C on t ex t ) { // 1. Mo v e c o n t ext f o r bi g g e r l in e H e i g ht var s hi f ted = c o n t e xt shi f t ed .t ra n s lat e B y (x: 0, y: l ine H e i gh t ) f o r l ine i n la yo ut { f o r r un i n l ine { / / 2. Ca l c u late f u rig an a p o si t i on l e t b ound s = l i ne . ty po g r a p h i c B o und s l e t x = b ound s . rect .m idX / / C en te r A lig n m ent l e t y = b ound s . rect .m inY } } }
  9. ू ͭͲ Small Text above base characters ։ൃऀ developer Center

    alignment (Furigana < Base) fu n c dr aw ( la yo ut : T e xt . La yo ut , i n c o n t e xt : i n o u t G ra p h i cs C on t ex t ) { // 1. Mo v e c o n t ext f o r bi g g e r l in e H e i g ht var s hi f ted = c o n t e xt shi f t ed .t ra n s lat e B y (x: 0, y: l ine H e i gh t ) f o r l ine i n la yo ut { f o r r un i n l ine { / / 2. Ca l c u late f u rig an a p o si t i on l e t b ound s = l i ne . ty po g r a p h i c B o und s l e t x = b ound s . rect .m idX / / C en te r A lig n m ent l e t y = b ound s . rect .m inY / / 3. D raw Furi g an a A n d Ba s e Ch a r a c te r l e t ru b y R e s o l v e d = sh i f t ed . re s o l ve ( T e xt ( T EXT ) . font (. c a p tion )) s hi f ted .dr aw ( ru b y R e s o l v e d , a t : . i n i t(x: x, y: y), a nch o r : . b ottom ) s hi f ted .dr aw ( ru n ) // D ra w Ba s e Cha r a c te r } } }
  10. All over the world Center alignment (Furigana > Base) //

    W i dth ca l cu la ti on l e t b as eW i dth = ru n . ty po g r a p h i c B o und s .w i dth l e t ru b y R e s o l v e d = shi f ted . re s o l ve ( T e xt ( ru b y C ha rs). f ont (. c a ptio n )) l e t ru b yW i dth = ru b y R e s o l v e d . me as u re( i n: m e as u r eS ize ).w i dth l e t extra Wi dth = m ax (0, ru b yW i dth - b as eWi dth) l e t p ad d i ng = extr aWi dth / 2 // D raw b as e text var s = s hi f ted s.t ra n s lat e B y (x: p ad d i n g , y: 0 ) s.dr aw ( ru n ) // D raw F uri g an a l e t x = r un . ty po g r a p h i c B o und s . re ct .m i dX + p ad d i ng l e t y = r un . ty po g r a p h i c B o und s . re ct .m i nY shi f ted .dr aw ( ru b y R e s o l v e d , a t : . i n i t(x: x, y: y), a nch or : . bott om ) // A dvanc e f o r n e x t run c o n t ext .t ra n s lat e B y (x: extraW i dth, y: 0 ) ͔Β ੈքதO O
  11. ੈքத ੈքத ͔Β All over the world ੈքத ͔Β All

    over the world ↓Move Context c o n t ext .t ra n s lat e B y (x: extraW i dth, y: 0 )