Indexへ
(14016)//【14009】→(14020)
------------------------
【タイトル】文字の終点座標
【記事番号】 14009 (*)
【 日時 】04/02/20 15:41
【 発言者 】ひでと icseisak@triton.ocn.ne.jp

はじめまして。今外変を勉強中です。
外変のBatファイルで文字の位置を取得したり、設定するのに、
文字の始点と終点の座標をあつかっているようですが、
文字列の画面上の大きさと関係しているようです。

外変で文字を作成するとき、センター合わせ等の処理で、
文字の画面上の大きさを計算する必要があるのではないでしょうか。
文字の始点から終点までの距離を文字列、フォント等で求めることはできますか。


Indexへ
(14009)←【14020】→(14030)
------------------------
【タイトル】Re: 文字の終点座標
【記事番号】 14020 (14009)
【 日時 】04/02/20 18:58
【 発言者 】makuma makuma@desu.ne.jp

hcw の対応幅×文字列数+(hcd の対応ピッチ×文字列数-1)ですね。


Indexへ
(14020)←【14030】→(14035)
------------------------
【タイトル】Re(1):文字の終点座標
【記事番号】 14030 (14009)
【 日時 】04/02/20 23:50
【 発言者 】Yacht za79d@hotmail.com

ひでとさん、こんにちは。
makumaさん、お疲れさまです。

実は、文字間隔がある場合は文字列末尾の全角/半角で文字長が少し違います。

半角文字は、文字幅と直後の文字間隔が、共にhcw・hcdの1/2になっています。
つまり、文中だと半角二字で全角1字の文字間隔・文字幅と等しくなりますが、
文末だと末尾の文字間隔がないので少々変わってきます。

外変を作るなら、半角1文字分(1バイト)を基準にした方が色々便利ですので、
文字列を半角換算でn文字(=nバイト)とすると、末尾が半角の場合、
L=n*hcw/2+(n-1)*hcd/2   ですが、末尾が全角だとさらにhcd/2短くなって、
L=n*hcw/2+(n-2)*hcd/2   になります。
ただし、上記は図寸なので、実際はこれにグループ縮尺を掛ける必要があります。

jgawkなら簡単なfunctionを作ってあるので、必要であれば書き込みします(^^


Indexへ
(14030)←【14035】→(14043)
------------------------
【タイトル】Re: Re(1):文字の終点座標
【記事番号】 14035 (14030)
【 日時 】04/02/21 10:03
【 発言者 】makuma makuma@desu.ne.jp

Yachtさん フォロー有り難うございます。

半角の場合を考えていませんでした。

でもそんなレアケースがあるのは知りませんでした。
というか気が付いていなかった。(^^ゞ

つまり、123 と 12 と 12 の場合でhcw=5、hcd=1の場合

全てバイト数は同じですが、文字列の長さは
123が 2.5+0.5+2.5+0.5+2.5=8.5 であるのに対して
12は 2.5+0.5+5=8 であり、
12は 5+1+2.5=8.5 となるんですね。

しっかり、0.5(hcd/2)の差が出ますね。

>jgawkなら簡単なfunctionを作ってあるので、必要であれば書き込みします(^^

よろしければ私も知りたいので教えてください。


Indexへ
(14035)←【14043】→(14046)
------------------------
【タイトル】Re:たいした物では無いですが
【記事番号】 14043 (14035)
【 日時 】04/02/21 13:15
【 発言者 】Yacht za79d@hotmail.com

makumaさん、こんにちは。

たいしたモノではありませんが・・・(^^ゞ

#文字長を求める関数 m_len()
#substr関数で文字列の最後の1バイトを抜き出そうとする。
#このとき、末尾が全角だと抜き出しに失敗?して空文字列が返るのでそれを利用する。
#
#引数 str:文字列 mh:文字幅 md:文字幅
function m_len(str,mh,md  ,mc,ml){
  mc=length(str)     #文字数:バイト
  ml=mc*mh/2+(mc-1)*md/2 #とりあえず全部半角として求める
  if(substr(str,mc,1)=="")ml=ml-md/2 #末尾全角ならさらにmd/2を減ずる
  return ml
}

実際に使っているのは上記を一行にした以下です。ブラウザだと改行されるかもしれま
せんがreturn文一行しかありません。
substr関数での返り値をそのまま条件分岐に利用しています。(空文字列だとfalse)

function m_len(str,mh,md){
return substr(str,length(str),1) ? length(str)*mh/2+(length(str)-1)*md/2 : length(str)*mh/2+(length(str)-2)*md/2
}

さらに、制御文字と埋め込み文字に対応した物もあるのですが、新規文字で無い限り
jw_temp.txtの4,5番目の座標で求まるので余り使い道が無いんです・・・(^^ゞ


Indexへ
(14043)←【14046】→(14076)
------------------------
【タイトル】有り難うございました。
【記事番号】 14046 (14043)
【 日時 】04/02/21 15:09
【 発言者 】makuma makuma@desu.ne.jp

なるほど、参考になりました有り難うございました。

>さらに、制御文字と埋め込み文字に対応した物もあるのですが、新規文字で無い限り
>jw_temp.txtの4,5番目の座標で求まるので余り使い道が無いんです・・・(^^ゞ

そういえば、制御文字と埋め込み文字はまた長さが特殊ですね。
考えたこと無かった...。これ考えると$fとか$Fなんかはどうしよう...(^^ゞ
今は追求するの止めとこう(笑)

ひでとさんは解決したかな?


Indexへ
(14046)←【14076】→(14109)
------------------------
【タイトル】Re(1):たいした物では無いですが
【記事番号】 14076 (14043)
【 日時 】04/02/23 11:05
【 発言者 】ひでと icseisak@triton.ocn.ne.jp

ご挨拶がおそくなって大変申し訳ありませんでした。
良く理解して、大事に使わせていただきます。ありがとうございました。


Indexへ
(14076)←【14109】→(14118)
------------------------
【タイトル】Re(2):文字の終点座標
【記事番号】 14109 (14030)
【 日時 】04/02/24 14:38
【 発言者 】ひでと icseisak@triton.ocn.ne.jp

教えていただいた事を参考にして試してみたのですが、少し違っているように思います。
試したところでは、一文字一文字が全角か半角かによって変わってくるようです。
全角の場合はjwの文字幅、その間隔もjwの文字間隔
半角の場合は文字幅、文字間隔ともに半分になってそれらを合計するみたいです。
初心者ではありますが、参考までにVBでの処理を作って試してみました。


Function m_len(str, mh, md, curScale)
' str:文字列 mh:jw全角文字幅 md:jw文字間隔 curScale:書き込みレイヤスケール
  For i = 1 To Len(str)
    M = LenB(StrConv(Mid(str, i, 1), vbFromUnicode))
    If M = 1 Then '半角の場合
      m_len = m_len + mh / 2 '半角文字の幅を加えて
      If i <> Len(str) Then m_len = m_len + md / 2 '文字間隔の半分を加える
    End If
    
    If M = 2 Then '全角の場合
      m_len = m_len + mh '全角文字の幅を加えて
      If i <> Len(str) Then m_len = m_len + md '文字間隔を加える
    End If
  Next i
  m_len = m_len * curScale
End Function


Indexへ
(14109)←【14118】→(14145)
------------------------
【タイトル】RE: Re(2):文字の終点座標
【記事番号】 14118 (14109)
【 日時 】04/02/24 15:58
【 発言者 】Yacht za79d_NOSPAM@hotmail.com

ひでとさん、こんにちは。

あってると思うのですが・・・(^^ゞ

私はエクセルVBAしか知らないので間違っているかもしれませんが、
jgawkのlength関数は、VBAのLenB関数に当たります。( Len関数に当たるのはjlength関数)
同様にsubstr関数はVBAのMidB関数です。(同様にMid関数はjsubstr関数)
おそらくこのあたりの関数の違いで、間違ったように感じたのだと思います

私が前々回のコメントで
>つまり、文中だと半角二字で全角1字の文字間隔・文字幅と等しくなりますが、
と書いたように、制御文字が無い場合、文中の全角半角は文字長には関係ありません。
その代わりすべて半角で計算する、と言うことです。

そのように考えると、エクセルVBA風に書くとこんな感じでどうでしょう?

'str:文字列 mh:jw全角文字幅 md:jw文字間隔 curScale:書き込みレイヤスケール
Function m_len(str, mh, md, curScale)
  'Mid関数で最後の1文字を抜き出したものと
  'MidB関数で最後の1文字を抜き出したものが一致すれば末尾が半角
  If Mid(str,Len(str),1)= MidB(str,LenB(str),1) Then
    m_len=LenB(str)*mh/2+(LenB(str)-1)*md/2
  else
    m_len=LenB(str)*mh/2+(LenB(str)-2)*md/2
  End if

  m_len=m_len*curScale
End Function

今うろ覚えで書いたので間違っているかもしれませんが、その時はどうかご容赦を・・・(^^ゞ


Indexへ
(14118)←【14145】→(14167)
------------------------
【タイトル】RE2: Re(2):文字の終点座標
【記事番号】 14145 (14118)
【 日時 】04/02/24 21:42
【 発言者 】makuma makuma@desu.ne.jp

お二人のを見て弄ってみました。
こんな感じで良いのでは?
若葉ちゃんなので間違いがあったらご指摘ください。m(_"_)m

'str:文字列 mh:jw全角文字幅 md:jw文字間隔 curScale:書き込みレイヤスケール
Function m_len(str, mh, md, curScale)
  'StrConvかけてやらないと半角全角ともに2バイトになっちゃうので。
  strLen = LenB(StrConv(str, vbFromUnicode))
  'Right関数で最後の1文字を抜き出したものが1バイトであれば末尾が半角
  If LenB(StrConv(Right(str, 1), vbFromUnicode))= 1 Then
    m_len=LenB(strLen)*mh/2+(LenB(strLen)-1)*md/2
  else
    m_len=LenB(strLen)*mh/2+(LenB(strLen)-2)*md/2
  End if

  m_len=m_len*curScale
End Function

このズレの原因が、hcw=5、hcd=1の場合

1234(半角3個)→ 2.5+0.5+2.5+0.5+2.5+0.5+2.5=11.5
123(半角+全角)→ 2.5+0.5+2.5+0.5+5=11
123(全角+半角)→ 5+1+2.5+0.5+2.5=11.5
12(全角+全角)→ 5+1+5=11

これらは全てバイト数は同じですが一様に差が出ます。

と、最後の文字のあとに来るべきピッチがmdであるかmd/2であるかの差が原因です。
つまり、最後の文字が全角だから...というより、全角か半角かの差です。

ですから、その判定すればクリア出来る...はず。
如何でしょうか?


Indexへ
(14145)←【14167】→(14198)
------------------------
【タイトル】RE3: 文字の終点座標
【記事番号】 14167 (14145)
【 日時 】04/02/25 10:34
【 発言者 】Yacht za79d_NOSPAM@hotmail.com

makumaさん、こんにちは。

LenBは半角でも2バイトを返すんですね・・・知りませんでした(^^ゞ
それなら、ひでとさんが間違っているとおっしゃるのも判ります(^_^)
勉強になりました。ありがとうございます。m(__)m

>ですから、その判定すればクリア出来る...はず。

そうです。要は、文字列のバイト数と最後の文字の全角/半角の判定だけで良い、
と言うことを私も言いたかったんです(^^ゞ

もちろん、ひでとさんのようなやり方でも全く問題ないです。
私も制御文字考慮の方はひでとさんのような方式でやってます。

掲示板の皆さん、くだらないレスでツリーを上げてスミマセンm(__)m


追伸
makumaさんのコード、strlen代入行でLenB処理しているので、文字長計算行ではLenBが
無くてもいいですね。そうすれば、ひでとさんのもmakumaさんのも私のjgawkスクリプトも
同じ数値を返してくれています(^_^)


Indexへ
(14167)←【14198】→(14200)
------------------------
【タイトル】RE4: 文字の終点座標
【記事番号】 14198 (14167)
【 日時 】04/02/25 17:28
【 発言者 】makuma makuma@desu.ne.jp

>makumaさんのコード、strlen代入行でLenB処理しているので、文字長計算行ではLenBが
>無くてもいいですね。そうすれば、ひでとさんのもmakumaさんのも私のjgawkスクリプトも
>同じ数値を返してくれています(^_^)

あぁ...ほんとだ、というか入れちゃダメじゃん。(@o@)

これだから、若葉ちゃんは困る。

正しくは、

'str:文字列 mh:jw全角文字幅 md:jw文字間隔 curScale:書き込みレイヤスケール
Function m_len(str, mh, md, curScale)
  'StrConvかけてやらないと半角全角ともに2バイトになっちゃうので。
  strLen = LenB(StrConv(str, vbFromUnicode))
  'Right関数で最後の1文字を抜き出したものが1バイトであれば末尾が半角
  If LenB(StrConv(Right(str, 1), vbFromUnicode))= 1 Then
    m_len=strLen*mh/2+(strLen-1)*md/2
  else
    m_len=strLen*mh/2+(strLen-2)*md/2
  End if

  m_len=m_len*curScale
End Function


Indexへ
(14198)←【14200】//(14011)
------------------------
【タイトル】Re(1):RE4: 文字の終点座標
【記事番号】 14200 (14198)
【 日時 】04/02/25 17:46
【 発言者 】ひでと icseisak@triton.ocn.ne.jp

>'str:文字列 mh:jw全角文字幅 md:jw文字間隔 curScale:書き込みレイヤスケール
>Function m_len(str, mh, md, curScale)
>  'StrConvかけてやらないと半角全角ともに2バイトになっちゃうので。
>  strLen = LenB(StrConv(str, vbFromUnicode))
>  'Right関数で最後の1文字を抜き出したものが1バイトであれば末尾が半角
>  If LenB(StrConv(Right(str, 1), vbFromUnicode))= 1 Then
>    m_len=strLen*mh/2+(strLen-1)*md/2
>  else
>    m_len=strLen*mh/2+(strLen-2)*md/2
>  End if
>
>  m_len=m_len*curScale
>End Function

皆様、色々と教えていただき有難うございました。
私が考えたものは、かなり効率が悪い方法だったのですね。
発想の転換が大事だとつくづく思いました。何分素人なもので、試行錯誤の繰り返しです。大事に使わせていただきます有難うございました。