質問する
0

Drawの図でサイズを入力するが、再表示すると誤差が表示する。

質問日 2018-03-16 10:00:26 +0200

通りすがり のGravatar画像

updated 2018-03-16 10:31:34 +0200

四角の図を書いて、プロパティのサイズを幅20、高10と入力する。

その後再びプロパティのサイズを見ると幅19.99、高10.01 と表示される。

寸法線などでの寸法は、正しく幅20高さ10と表示されるので、印刷すれば支障は無いといえば無いのですが、どうにも気持ち悪い。

表示が小数点2桁まで出ているので、これが小数点1桁表示にする事が出来れば、多分四捨五入で表面上正しく表示してストレスが無くなるのですが、いい方法がないものでしょうか? LiberOffice Ver 6.0.2.1

画像の説明

edit retag flag offensive close merge delete

2 Answer

1

回答日 2018-03-18 22:38:50 +0200

himajin100000 のGravatar画像

updated 2018-07-19 03:29:50 +0200

2018-04-07 ほぼ全面改訂

自信なし。回答欄使うけど、回答にあらず。強い違和感あるけど仕様…かなぁ?ズレが見られるのはサイドバーのパネルだけでコンテキストメニューから呼び出すダイアログは問題ないので仕様ではない

通りすがり氏の実装に関する推測は正しい。ログを取ってみたら394とそこから10.01が出てきていた。(計算の一部数値をhimajin100000側で書き換えてます)

多分、内部での計算は全てインチで行い、表示時にcmに変換するのでしょう。 問題は、内部計算毎に小数点3位で四捨五入して小数点2桁にしているのではないのでしょうか。 10cm=3.93700787401575in→3.94in=3.94x2.54=10.0076 →10.01 20cm=7.8740157480315in→7.87in=7.87x2.54=19.9898 → 19.99

で、以下、やや推測込み。

  1. Writer起動
  2. Writerでサイドバーを表示する。この段階では「位置とサイズ」セクションはない。
  3. 長方形を図形描画すると、サイドバーのパネル表示に必要になったときにPosSizePropertyPanelのコンストラクタが走るようで、初期値の設定に関わる。
    https://opengrok.libreoffice.org/xref...
  4. mpBindings->Update( SID_ATTR_METRIC );が実行されたとき、MetricStateが走り https://opengrok.libreoffice.org/xref...
    https://opengrok.libreoffice.org/xref...
    869行目でメンバ変数meDlgUnitに代入がなされる。このメンバ変数に代入が行われるのは、ソースコード上ここだけである。
  5. ところで、 SetFieldUnitは、指定されたコントロールの内部で保持するときの単位を指定している。 https://opengrok.libreoffice.org/xref...

  6. もう一度コンストラクタを見てみよう。
    mpBindings->Update( SID_ATTR_TRANSFORM_WIDTH );
    mpBindings->Update( SID_ATTR_TRANSFORM_HEIGHT );
    mpBindings->Update( SID_ATTR_TRANSFORM_PROTECT_SIZE );
    mpBindings->Update( SID_ATTR_METRIC );
    の順であるから、SID_ATTR_TRANSFORM_WIDTHの段階では、まだSID_ATTR_METRIC用の処理は走ってない。
    よって、内部設定用に使われる単位はmeDlgUnitの初期値のFUNIT_INCHである。
    Writerで用いる単位を設定画面からセンチメートルにしていた場合
    MetricStateで呼ばれるGetCurrentUnitが返す値はFUNIT_CMだったようなので、
    mpBindings->Update( SID_ATTR_METRIC );
    mpBindings->Update( SID_ATTR_TRANSFORM_WIDTH );
    mpBindings->Update( SID_ATTR_TRANSFORM_HEIGHT );
    mpBindings->Update( SID_ATTR_TRANSFORM_PROTECT_SIZE );
    となっていれば、0.01cmのズレは発生しないように思う。少なくとも手元のビルドでは問題ない。

2018-04-20 追記: cmをinchに変換するからずれるのであって、コンストラクタがPozSizePropertyPanelの数値の内部管理meDlgUnit(後にSetFieldUnitでMetricFieldの単位meUnitにも利用される)をcmで行うように変えれば単位同じだからずれないだろう、という策なので、コンストラクタ実行後にツール→オプションで内部管理単位をINCHに変更してOKしてから再びCMに戻すとズレます。このコード変更は「軽減するだけ」です。

ここからコード上未調査・未解決。話はここで終わらないのだ。どのタイミングでコンストラクタが走っているのか、という問題だ。

問題が起きているバージョンで話を進める。なお、以下の項目の手順は互いに独立である。

  1. 長方形一つを描画し、サイドバーから幅を10.00cmにし、ツールバーから矢印を選択、長方形以外のところをクリックすると、当該パネルがなくなり、もう一度長方形を選択したとき、コンストラクタが走ってずれる。
  2. 長方形二つを描画し、一方の長方形を選択している状態でサイドバーから幅"10.00cm"を入力する。 他方の長方形を選択してから、元の長方形を選択する。このときはずれない。
  3. 長方形一つを描画し、サイドバーから幅"10.00cm"を入力する。サイドバー横のタブからサイドバーの内容を一旦ナビゲータに切り替えてからプロパティに戻す。このときもずれない。
  4. 長方形一つを描画し、サイドバーから幅"10.00cm",高さ"10.00cm"を入力する。ここで[Tools]-[Options]-[LibreOfficeDev]-[LibreOffice Writer]のMesurementUnitをPicaにし、OKを押してダイアログを閉じる。再び設定画面をMeasurement UnitをCentimeterに戻し、長方形を選択する。このときサイドバーに表示されている数値がおかしくなる。ただし、一旦長方形以外のところをクリックしてから長方形をクリックすると10.01cmに戻る。

2018-04-14 追記: 原因の想像はついたけど、治し方が頭の中で固まらない
1000 * 10^(-2) cm = 2362 * 10^(-2) pc
Expected1: 0 cm< 1000 * 10^(-2) cm < 2100 * 10^(-2) cm - 50 * 10^(-2) cm(Border)
Expected2: 0 pc < 2362 * 10^(-2) pc - border < 4960.6 * 10^(-2) pc
Actual: 2100 * 10^(-2) pc - 50 * 10^(-2) pc < 2362 * 10^(-2) pc2050 * 10^(-2) pc
このときの「上限」は、長方形の左上の座標から、紙右端までの距離に依存するはず。一応念の為余白ゼロ、アンカーはページに、して紙の左上端から長方形を描いて実験した。

2018-04-18 追記:

再び、大まかに理解した。そのうち英語でバグレポ、場合によってはパッチも書くかもしれませんが、面倒なのでそれなりに遅れる予定。以下罫線等の話は無視する。

  • 一応念の為SetPosSizeMinMax()はSetFieldUnitよりも前で呼び出し、内部で使用されているSetMaxやSetMinは第二引数に単位を指定するようにした。不要かもしれない。
  • MetricFieldは最小値(0)、最大値(21)、現在値(10)を保持する。各数値の単位については継承元MetricFormatterのメンバ変数のmeUnit(cm)で統一されている。
  • void MetricFormatter::SetUnit( FieldUnit eNewUnit )は各数値をそのままに、「単位だけ」変更する。最小値は0 pc, 最大値は21pcだ こいつは表示文字列の生成等のためにReformatAllからvoid MetricFormatter::Reformat()を呼ぶ。
  • そこからの階層では当該文字列の数値(10.00)と文字列中の単位(cm)を取り出し、設定された単位への変換(23.62pc)を行い、新たな最小値、最大値の範囲内にあるか調べ、なかったときは、最小値または最大値にそれぞれ設定し直される。(21,pc,"21pc")。
  • こいつを使うvoid MetricField::SetUnit( FieldUnit nNewUnit )やvoid SetFieldUnit( MetricField& rField, FieldUnit eUnit, bool bAll)は最大値と最小値の問題には気づいたみたいで、21cmをtwipに変換した数値とかを変数に避けておいて、後でvoid MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )とかで設定し直すんだけど、 現在値は再設定しない。最初の地点で単位変更前の現在値をtwipで取り出しておいて、あとにSetValueとかSetUserValueとかで代入してやれば治るかなあ?と思ってやってみたらとりあえずうまく動いてそうだ。あ、ちなみにSetMinやSetMaxもReformatAllを呼びます。なおSetFieldUnitの第三引数はfalseである。関数の定義参照。

https://bugs.documentfoundation.org/s...
https://bugs.documentfoundation.org/s...

edit flag offensive delete link もっと
0

回答日 2018-03-20 04:53:07 +0200

通りすがり のGravatar画像

updated 2018-03-26 16:07:38 +0200

>himajin100000の回答から

多分、内部での計算は全てインチで行い、表示時にcmに変換するのでしょう。 問題は、内部計算毎に小数点3位で四捨五入して小数点2桁にしているのではないのでしょうか。

10cm=3.93700787401575in →3.94in=3.94x2.54=10.008 →10.01

20cm=7.8740157480315in →7.87in=7.87x2.54=19.990 →19.99

せめて内部的には、小数点4桁で四捨五入して小数点3桁で丸める。 cmに変換する最終形態にする時に小数点2桁にまとめるようにすると誤差は生じ難いと思います。 以上の修正は、根本的なことの様で困難な様でもあり、簡単に修正できるようなことでもあり。

少なくとも最終形態が小数点2桁なら、内部計算は小数点3桁以上の数値で行わなければ、誤差は必ず発生しますので、バクといえばバグです。

全て私の推測なので実際内部での計算が小数点2桁に丸められているのかは分かりません。

----- 20118/03/26 追加 -------------------------------------

>ズレが見られるのはサイドバーのパネルだけでコンテキストメニューから呼び出すダイアログは問題ない

これには、気が付きませんでした。いつもサイドメニューを表示してその中で数値を変更していたものですので、F4を押してのダイアログは使用していませんでした。

普通の人は、サイドバーでもコンテキストメニューでもサイズは同じ数値を表示すると思いますね。 という事は、その内サイドバーの方も修正されるのかもしれませんね。気長に待つか・・・・

edit flag offensive delete link もっと
ログイン/サインアップして回答する

質問ツール

2 followers

Stats

Asked: 2018-03-16 10:00:26 +0200

Seen: 105 times

Last updated: Jul 19