和田研フォントキットの肉付け処理を解き明かす - (2) -

和田研フォントキットの肉付け処理を解き明かす - (1) -を踏まえて。

さて、apply.lのskeleton2list関数の続きを解読して行こう。

      ; linkpoints に挿入する                                                                                                                 
      (do ((lll cpoint (cdr lll))
           (i 0 (1+ i)))
          ((atom lll))
          (cond ((zerop i)
                 (setq flag 0))                         ; 最初の点                                                                            
                ((atom (cdr lll));(eq i (1- npoint))                                                                                          
                 (setq flag 1))                         ; 最後の点                                                                            
                (t (setq flag 2)))                      ; 中間点                                                                              
          (setq link (assq 'link (cdr (assq (car lll) linkpoints))))
          (rplacd link (cons (list type flag tmpline) (cdr link))))

この部分ではcpointの要素一つ一つに対して処理を行う。「六」の場合cpointは「( (YOKO (0 1) (LINK 2)) (TATE (3 2)) (HIDARI (4 5 6)) (MIGI (7 8 9)))」となっている。そして次にそれぞれの点に対してフラグを設定して行く。開始点ならば0、終端点なら1、中間点なら2といった具合だ。例えば(HIDARI (4 5 6))の場合は点4 -> 開始点、 点5 -> 中間点、点6 -> 終端点となるので、それぞれ0・2・1のフラグが付けられる。このフラグを先ほど生成したlinkpointに付け加える。

      (do ((lll lpoint (cdr lll)))
        ((atom lll))
        (setq link (assq 'link (cdr (assq (car lll) linkpoints))))
        (rplacd link (cons (list type 2 tmpline) (cdr link)))))

同じくlpointについてもlinkpointsに対して追加していく。「六」の場合lpointは「(LINK 2)」となっている。結合部分が一ヶ所しか無い為だ。この二つのブロックでcpoint, lpointを追加した後のlinkpointsは以下の様になっている。

((9
  (LINK
   (MIGI 1
    (LINES
     (((ANGLE 218.32162 172.70253) (BEZIER 240.78387 252.33307)
       (BEZIER 282.70975 325.53644) (ANGLE 343.59192 391.91068))
      ((ANGLE 243.34512 165.64388) (BEZIER 264.6463 241.15836)
       (BEZIER 304.2796 310.5883) (ANGLE 362.75232 374.33572)))))))
 (8
  (LINK
   (MIGI 2
    (LINES
     (((ANGLE 218.32162 172.70253) (BEZIER 240.78387 252.33307)
       (BEZIER 282.70975 325.53644) (ANGLE 343.59192 391.91068))
      ((ANGLE 243.34512 165.64388) (BEZIER 264.6463 241.15836)
       (BEZIER 304.2796 310.5883) (ANGLE 362.75232 374.33572)))))))
 (7
  (LINK
   (MIGI 0
    (LINES
     (((ANGLE 218.32162 172.70253) (BEZIER 240.78387 252.33307)
       (BEZIER 282.70975 325.53644) (ANGLE 343.59192 391.91068))
      ((ANGLE 243.34512 165.64388) (BEZIER 264.6463 241.15836)
       (BEZIER 304.2796 310.5883) (ANGLE 362.75232 374.33572)))))))
 (6
  (LINK
   (HIDARI 1
    (LINES
     (((ANGLE 122.954636 169.00656) (BEZIER 98.96448 244.85938)
       (BEZIER 59.81082 313.89523) (ANGLE 5.2062836 376.45114))
      ((ANGLE 147.74434 176.84686) (BEZIER 122.66639 256.1391)
       (BEZIER 81.58706 328.4854) (ANGLE 24.793728 393.54886)))))))
 (5
  (LINK
   (HIDARI 2
    (LINES
     (((ANGLE 122.954636 169.00656) (BEZIER 98.96448 244.85938)
       (BEZIER 59.81082 313.89523) (ANGLE 5.2062836 376.45114))
      ((ANGLE 147.74434 176.84686) (BEZIER 122.66639 256.1391)
       (BEZIER 81.58706 328.4854) (ANGLE 24.793728 393.54886)))))))
 (4
  (LINK
   (HIDARI 0
    (LINES
     (((ANGLE 122.954636 169.00656) (BEZIER 98.96448 244.85938)
       (BEZIER 59.81082 313.89523) (ANGLE 5.2062836 376.45114))
      ((ANGLE 147.74434 176.84686) (BEZIER 122.66639 256.1391)
       (BEZIER 81.58706 328.4854) (ANGLE 24.793728 393.54886)))))))
 (3
  (LINK
   (TATE 0
         (LINES
          (((ANGLE 188.42883 15.0) (ANGLE 188.42883 93.091))
           ((ANGLE 214.42883 15.0) (ANGLE 214.42883 93.091)))))))
 (2
  (LINK
   (TATE 1
         (LINES
          (((ANGLE 188.42883 15.0) (ANGLE 188.42883 93.091))
           ((ANGLE 214.42883 15.0) (ANGLE 214.42883 93.091)))))
   (YOKO 2
         (LINES
          (((ANGLE 17.00909 107.826355) (ANGLE 383.90402 107.82636))
           ((ANGLE 17.00909 81.826355) (ANGLE 383.90402 81.82636)))))))
 (1
  (LINK
   (YOKO 1
         (LINES
          (((ANGLE 17.00909 107.826355) (ANGLE 383.90402 107.82636))
           ((ANGLE 17.00909 81.826355) (ANGLE 383.90402 81.82636)))))))
 (0
  (LINK
   (YOKO 0
         (LINES
          (((ANGLE 17.00909 107.826355) (ANGLE 383.90402 107.82636))
           ((ANGLE 17.00909 81.826355) (ANGLE 383.90402 81.82636)))))))) 

一つ一つの構造は次のようになっている。

(点番号
 (LINK
   (線のタイプ フラグ(開始点0、終端点1、中間点2)
    (LINES
     (線のリスト)))
   (線のタイプ フラグ(開始点0、終端点1、中間点2)
    (LINES
     (線のリスト)))

))

LINK以下のリストの数は、その点を通る線の本数を現している。例えば点番号2においては二つの線が交わっているため、二つのエントリが有る。三つ、四つとなった場合は同様に数が増える。次の部分はこのデータを利用する。

    (do ((ll linkpoints (cdr ll)))
      ((atom ll))
      (setq link (assq 'link (cdar ll)))                                                                                                            
      (cond
       ((eq 4 (length link)) ; 3本のストロークが集まる点                     
        (ほげほげーーーーーー))
       ((eq 3 (length link)) ; 2本のストロークが集まる点
        (ほげほげーーーーーー))
       ((and (eq 2 (length link))(<= 0 (cadadr link) 1)) ; 1本のストロークのみ
        (setq part1 (cadr link))
        (setq type1 (cadr part1))
;            (setq cross (cross2point part1 (point-n (caar ll) points)))                                                                      
        (setq cross (cross2point part1 (nth (caar ll) points)))
        (setq kazari
              (findkazari part1 part1 0 1 cross tag))
        (nconc (assq 'lines (cddr part1))
               (cons (cons (- -1 type1) kazari) nil))
        )))

この部分では3本、2本のストロークが重なっている場合・1本のストロークのみの場合を処理している。3本、2本の部分は長すぎるので今は割愛。色々hogeってるようだ。ここでは1本の場合の時の処理を見ていく事にしよう。

        (setq part1 (cadr link))
        (setq type1 (cadr part1))
;            (setq cross (cross2point part1 (point-n (caar ll) points)))                                                                      
        (setq cross (cross2point part1 (nth (caar ll) points)))
        (setq kazari
              (findkazari part1 part1 0 1 cross tag))
        (nconc (assq 'lines (cddr part1))
               (cons (cons (- -1 type1) kazari) nil))

点番号9の場合は以下のように値が代入される。

---- part1 ----
(MIGI 1
 (LINES
  (((ANGLE 218.32162 172.70253) (BEZIER 240.78387 252.33307)
    (BEZIER 282.70975 325.53644) (ANGLE 343.59192 391.91068))
   ((ANGLE 243.34512 165.64388) (BEZIER 264.6463 241.15836)
    (BEZIER 304.2796 310.5883) (ANGLE 362.75232 374.33572))))) 

---- type1 ----
1

---- cross ----
#((343.59192 391.91068) (362.75232 374.33572) (326.01694 372.7503)
  (345.17734 355.17535)) 

---- kazari ----
((ANGLE 341.2159 389.32034) (ANGLE 365.12833 376.92606)) 

cross(point2cross関数)の役割がまだ掴めていないが、要するにpart1, cross, tagから対応する「kazari」を取得して来てlinkpointにくっつけるという処理をしている様である。この辺りは詳しく仕組みを見ていくべきだと思うが、とりあえずパスしておこう。この処理をすべての点について終えた後のlinkpointsは次のようになる。

((9
  (LINK
   (MIGI 1
    (LINES
     (((ANGLE 218.32162 172.70253) (BEZIER 240.78387 252.33307)
       (BEZIER 282.70975 325.53644) (ANGLE 343.59192 391.91068))
      ((ANGLE 243.34512 165.64388) (BEZIER 264.6463 241.15836)
       (BEZIER 304.2796 310.5883) (ANGLE 362.75232 374.33572)))
     (2 341.2159 389.32034) (3 365.12833 376.92606)
     (-2 (ANGLE 341.2159 389.32034) (ANGLE 365.12833 376.92606)) (-1)))))
 (8
  (LINK
   (MIGI 2
    (LINES
     (((ANGLE 218.32162 172.70253) (BEZIER 240.78387 252.33307)
       (BEZIER 282.70975 325.53644) (ANGLE 343.59192 391.91068))
      ((ANGLE 243.34512 165.64388) (BEZIER 264.6463 241.15836)
       (BEZIER 304.2796 310.5883) (ANGLE 362.75232 374.33572)))
     (2 341.2159 389.32034) (3 365.12833 376.92606)
     (-2 (ANGLE 341.2159 389.32034) (ANGLE 365.12833 376.92606)) (-1)))))
 (7
  (LINK
   (MIGI 0
    (LINES
     (((ANGLE 218.32162 172.70253) (BEZIER 240.78387 252.33307)
       (BEZIER 282.70975 325.53644) (ANGLE 343.59192 391.91068))
      ((ANGLE 243.34512 165.64388) (BEZIER 264.6463 241.15836)
       (BEZIER 304.2796 310.5883) (ANGLE 362.75232 374.33572)))
     (2 341.2159 389.32034) (3 365.12833 376.92606)
     (-2 (ANGLE 341.2159 389.32034) (ANGLE 365.12833 376.92606)) (-1)))))
 (6
  (LINK
   (HIDARI 1
    (LINES
     (((ANGLE 122.954636 169.00656) (BEZIER 98.96448 244.85938)
       (BEZIER 59.81082 313.89523) (ANGLE 5.2062836 376.45114))
      ((ANGLE 147.74434 176.84686) (BEZIER 122.66639 256.1391)
       (BEZIER 81.58706 328.4854) (ANGLE 24.793728 393.54886)))
     (2 2.9575753 379.0273) (3 27.042437 390.9727)
     (-2 (ANGLE 2.9575753 379.0273) (ANGLE 27.042437 390.9727))
     (0 122.954636 169.00656) (1 142.65422 192.94095)
     (-1 (ANGLE 122.954636 169.00656) (BEZIER 159.75325 181.98729)
      (BEZIER 157.20819 190.03433) (ANGLE 142.65422 192.94095))))))
 (5
  (LINK
   (HIDARI 2
    (LINES
     (((ANGLE 122.954636 169.00656) (BEZIER 98.96448 244.85938)
       (BEZIER 59.81082 313.89523) (ANGLE 5.2062836 376.45114))
      ((ANGLE 147.74434 176.84686) (BEZIER 122.66639 256.1391)
       (BEZIER 81.58706 328.4854) (ANGLE 24.793728 393.54886)))
     (2 2.9575753 379.0273) (3 27.042437 390.9727)
     (-2 (ANGLE 2.9575753 379.0273) (ANGLE 27.042437 390.9727))
     (0 122.954636 169.00656) (1 142.65422 192.94095)
     (-1 (ANGLE 122.954636 169.00656) (BEZIER 159.75325 181.98729)
      (BEZIER 157.20819 190.03433) (ANGLE 142.65422 192.94095))))))
 (4
  (LINK
   (HIDARI 0
    (LINES
     (((ANGLE 122.954636 169.00656) (BEZIER 98.96448 244.85938)
       (BEZIER 59.81082 313.89523) (ANGLE 5.2062836 376.45114))
      ((ANGLE 147.74434 176.84686) (BEZIER 122.66639 256.1391)
       (BEZIER 81.58706 328.4854) (ANGLE 24.793728 393.54886)))
     (2 2.9575753 379.0273) (3 27.042437 390.9727)
     (-2 (ANGLE 2.9575753 379.0273) (ANGLE 27.042437 390.9727))
     (0 122.954636 169.00656) (1 142.65422 192.94095)
     (-1 (ANGLE 122.954636 169.00656) (BEZIER 159.75325 181.98729)
      (BEZIER 157.20819 190.03433) (ANGLE 142.65422 192.94095))))))
 (3
  (LINK
   (TATE 0
         (LINES
          (((ANGLE 188.42883 15.0) (ANGLE 188.42883 93.091))
           ((ANGLE 214.42883 15.0) (ANGLE 214.42883 93.091)))
          (0 188.42883 15.0) (1 214.42883 29.3)
          (-1 (ANGLE 188.42883 15.0) (BEZIER 227.42883 18.119999)
           (BEZIER 227.42883 24.880001) (ANGLE 214.42883 29.3))
          (2 188.42883 97.42636) (3 214.42885 100.02637)))))
 (2
  (LINK
   (TATE 1
         (LINES
          (((ANGLE 188.42883 15.0) (ANGLE 188.42883 93.091))
           ((ANGLE 214.42883 15.0) (ANGLE 214.42883 93.091)))
          (0 188.42883 15.0) (1 214.42883 29.3)
          (-1 (ANGLE 188.42883 15.0) (BEZIER 227.42883 18.119999)
           (BEZIER 227.42883 24.880001) (ANGLE 214.42883 29.3))
          (2 188.42883 97.42636) (3 214.42885 100.02637)))
   (YOKO 2
         (LINES
          (((ANGLE 17.00909 107.826355) (ANGLE 383.90402 107.82636))
           ((ANGLE 17.00909 81.826355) (ANGLE 383.90402 81.82636)))
          (-2) (-1)))))
 (1
  (LINK
   (YOKO 1
         (LINES
          (((ANGLE 17.00909 107.826355) (ANGLE 383.90402 107.82636))
           ((ANGLE 17.00909 81.826355) (ANGLE 383.90402 81.82636)))
          (-2) (-1)))))
 (0
  (LINK
   (YOKO 0
         (LINES
          (((ANGLE 17.00909 107.826355) (ANGLE 383.90402 107.82636))
           ((ANGLE 17.00909 81.826355) (ANGLE 383.90402 81.82636)))
          (-2) (-1)))))) 

うーん、確かにさっきと比べて「飾り」がたくさん付いているようだ。おそらく、serifなんかを処理しているのかなぁ。とりあえずこの部分は「飾り付けをしている」というレベルで置いておこう。さて次のブロックに進もう。

    (do ((ll linelist (cdr ll))
         (part0 nil)
         (part1 nil))
      ((atom ll))
      (setq part0 (car (cadar ll)))
      (setq part1 (cadr (cadar ll)))
      (setq part2 nil part3 nil)
;      (pprint (cddar ll))                                                                                                                    
      (do ((lll (cddar ll) (cdr lll)))
          ((atom lll))
          (case (caar lll)
                (-2 (setq part3 (cond ((cdar lll)(cddar lll)))))
                (-1 (setq part2 (cond ((cdar lll)(reverse (cddar lll))))))
                (0 (setq part0 (change-head part0 (cdar lll))))
                (1 (setq part1 (change-head part1 (cdar lll))))
                (2 (setq part0 (change-tail part0 (cdar lll))))
                (3 (setq part1 (change-tail part1 (cdar lll))))
;                  (t (pprint (caar lll)))                                                                                                    
                   ))
      (push (append part0 part3 (reverse part1) part2) outline))
;    (break)                                                                                                                                  
  outline))

コメントゼロの糞コードである。この部分は-2 〜 3までの値を処理しているように見える。先ほどのlinkpointsと見比べる(linelistはlinkpointsを破壊的に変更すると同じように変更されている)と、どうやら-2 〜 3の数字は飾りの種類を現していそうだという事が分かる。まぁ種類に応じてなんらかの処理を行っているのだろう。そして結果をoutlineに押し込み、それを結果として返す。

これがskeleton2list関数の大まかな解析結果だ。次からはもう少し細かく見ていく事にしよう。

(続く)