2010/04/07

SVG で横書きの文字のまま、タテに表示

ポスト @ 1:09:29 | ,     

前回の続きです

横書きに表示されている文字をタテに表示するというのを挑戦してます。
今回は SVG を利用しているので、ほぼ全てが座標で表現されます。
こんな感じ↓

ブラウザで座標を考える場合 (0, 0) が左上になり、それよりも外側はブラウザの表示の外になります。

そこで、「美しい日本語」という文字列を (0, 0) からレンダリングするとこんな感じになります。

単純に考えれば、この文字列を 90° 垂直に回転 させれば、タテに表示されそうですがそうもいきません。
文字列を (0, 0) にレンダリングしてしまったので、そのまま回転させてしまうと、画面の外に出てしまいます。

ちなみに、SVG の回転は transform(rotate) を使うんですが、rotateの引数に rotate(rangle, cx, cy) と X座標(cx) と Y座標(cy) の回転位置を指定できるので、この引数を使い回転位置を調整します。

これで、回転位置を調整する事で無事表示領域内に文字列をタテに表示できるようになります。

(中略)

ということで、この SVG を使った実装を Figit に実装してみた。(CSSと合わせて左側にくっついてきます)
残念ながら、SVG をサポートしていない IE と 文字の rotate が上手くいかない Opera はちゃんと表示されません...。
Firefox や Webkit系(Safari, Chrome) などはちゃんと↓のように表示されているハズ...。(たぶん iPhone/Androidも大丈夫だと思う)

今回利用したソースは http://figit.net/js/pig.svg.js にもあるけど、ここにも一応書いておこう

if(typeof Pig == 'undefined'){
  var Pig = {};
}
Pig.SVG = {
  namespace: 'http://www.w3.org/2000/svg',
  create: function(tagName, attributes){
    attributes = attributes || {};
    var tag = document.createElementNS(Pig.SVG.namespace, tagName);
    Element.writeAttribute(tag, attributes);
    return tag;
  },
  createSVG: function (attribtues){
    return this.create('svg', attribtues);
  },
  createRect: function (attributes){
    return this.create('rect', attributes);
  },
  createText: function (attributes){
    return this.create('text', attributes);
  }
};
Pig.SVG.VarticalBox = Class.create({
  initialize: function (){
    var fontSize = document.body.getStyle('fontSize');
    this.fontSize = parseInt(fontSize);
  },
  create: function(_str, _style){
    var fontSize = this.fontSize;
    var strLength = _str.length;
    
    var chars = _str.toArray();
    var textLength = 0;
    for(var i = 0; i < chars.length; ++i){
      var ch = chars[i];
      // isAscii
      if(ch == escape(ch)){
        textLength += 0.5;
      } else {
        textLength += 1;
      }
    }
    
    // textLength + 2em(paddig-left: 1em, padding-right: 1em)
    var rectWidth = (textLength * (fontSize)) + (fontSize + fontSize);
    var rectHeight = fontSize * 3;
    var halfRectHeight = rectHeight / 2;
    var halfRectWidth = rectWidth / 2;
    
    var style = Object.extend({
      'backgroundColor': '#ddd',
      'borderColor': '#333',
      'opacity': 0.3,
      'color': '#333',
      'fontFamily': 'sans-serif'
    }, _style || {});
    
    var rect = Pig.SVG.createRect({
      'x': rectHeight,
      'y': 0,
      'width': rectWidth,
      'height': rectHeight,
      'fill': style.backgroundColor,
      'opacity': style.opacity,
      'stroke': style.borderColor,
      'transform': 'rotate(90, ' + rectHeight + ', 0)'
    });
    var text = Pig.SVG.createText({
      'x': halfRectHeight,
      'y': halfRectWidth,
      'fill': style.color,
      'font-family': style.fontFamily,
      'writing-mode': 'tb-rl',
      'glyph-orientation-vertica': '90',
      'text-anchor': 'middle',
      'alignment-baseline': 'central',
      'dominant-baseline': 'central',
      'transform': 'rotate(90, ' + halfRectHeight + ', ' +  halfRectWidth + ')'
    });
    text.textContent = _str;

    var svg = Pig.SVG.createSVG({
      'width': rectHeight,
      'height': rectWidth
    });
    svg.appendChild(rect);
    svg.appendChild(text);
    return svg;
  }
});

ということで、今後とも Figit に色々のっけていきます

2010/03/29

横書きのままタテに表示するアレ

ポスト @ 23:52:54 | ,     

最近よく見かけるようになった、スクロールバーのとこにくっついてくるアレ


(follow me とか)

(feedback とか)

問題は、これがスクロールについてくることじゃなくて、横書きなのに、縦に表示されているってこと。
これ、どうやるんだろう...。

(中略)

やっぱここは流行りのSVGだよね。ってことで、やってみた(注:Firefox,Chrome以外動かないと思う)
ref - http://xole.net/svg.html

横書きのままタテに表示されるようになったけど、リンクが動かない...。
しょうがないので、onclickで逃げる。
ソースは↓

(function (){
    var anchor = function (href, str){
        var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
        svg.setAttribute('width', 300);
        svg.setAttribute('height', 200);

        var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
        rect.setAttribute('x', 0);
        rect.setAttribute('y', 0);
        rect.setAttribute('width', 200);
        rect.setAttribute('height', 50);
        rect.setAttribute('fill', '#ccc');
        rect.setAttribute('opacity', 0.3);
        rect.setAttribute('stroke', '#333');

        var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        text.setAttribute('x', 50);
        text.setAttribute('y', 30);
        text.setAttribute('writing-mode', 'tb-rl');
        text.setAttribute('glyph-orientation-vertica', '90');
        text.setAttribute('fill', '#333');
        text.setAttribute('transform', 'rotate(90, 90, 90)');
        text.textContent = str;
        text.onclick = function(){location.href = href};

        text.appendChild(rect);
        svg.appendChild(text);

        //
        svg.style.display = 'block';
        return svg;
    };

    var element = document.createElement('div');
    element.style.position = 'absolute';
    element.style.left = 0;
    element.style.padding = 0;

    element.appendChild(anchor('http://www.google.co.jp/', 'こんにちは!'));
    element.appendChild(anchor('http://www.google.com/', 'hello world'));
    document.body.appendChild(element);
})();

他にいい方法あるんかな...。(やっぱ画像?)

Javascript Library 毎のパフォーマンス比較

ポスト @ 1:18:51 , 修正 @ 2010/04/01 0:45:56 | , , ,     

というこよで、貼ってみる

ちなみに DOM 操作編

やっぱ jQuery は早いねー

(2010/03/31追記)

出展元を書くのを忘れてました。
via - http://figit.net/post/644
(上記グラフは単位がmsになります)

さらに、元ネタは http://docs.jquery.com/Release:jQuery_1.3#Performanceがソースになります

2010/03/27

クックパッドのレシピ数

ポスト @ 12:19:26 |     

2010/03/26

やったー グラフ投稿サイトできたよー\(^o^)/

ポスト @ 22:47:26 , 修正 @ 2010/03/26 23:02:00 | ,     

合宿の成果第一段の グラフ投稿サイト「Figit」ができたよー
ref - http://figit.net/

コンセプトとか細かいことは @figit が考えているけど、どうやら世界一(?) シンプルなグラフ投稿サイトらしいよ!

今のところアカウント登録とか面倒な事は一切なしで、みんなグラフをガンガン投稿しまくれるよ!(性善説に基づいてるので、面倒な事は一切省いてシンプルに!)

僕たちが作りました


(オフィス出発前の画像を勝手に加工してみた)

バグや要望、質問などは figit.uservoice.com@figit_net へどうぞ。

2010/03/25

開発合宿。三日目

ポスト @ 10:01:34 | ,     

今日は最終日です。気合を入れていきましょー

(更新中)

(追記、すいません全然更新できませんでした...)

午前中

2泊3日の部屋を見て愕然とする...

その後、再びもくもく実装中...。

お昼

唯一の娯楽であるお昼を堪能
(写真は忘れてた...。)

午後

なんとかカタチになるサイトっぽくなってきた。
細かい部分の修正などをして、17時合宿を終える

(深谷での帰り道の一コマ)

解散

おわたー
ちょー疲れた合宿でした。
次回は座椅子を持っていくことにします。

合宿の成果

合宿の成果は近日公開します

開発合宿。二日目

ポスト @ 10:00:04 | ,     

この日は朝っぱらから雨。しかも寒い。
昨日と違い、みんな余裕が無い事に気づき、あまり写真は無し。
ってか開発の模様は全然書いてない...。

午前中

Skypeでビデオミーティング
skypeがあってよかった。

その後お昼までもくもく。

作業風景。静かです

お昼

どうやら近くにデニーズがあるらしい。...のでデニーズでお昼です


メニューの写真はこんな感じで大きなハンバーグだったのに...


実際はちょっと小さめ...orz

午後

もくもく

深夜

一通り作業も終わり、合宿で忘れてはならない3人大富豪大会へ...!

(成績表。何回やってるんだ...。3人で)

二日目終了〜


(↑ちなみにこれ、僕たちのアバターです)

2010/03/24

開発合宿。一日目

ポスト @ 0:39:43 | ,     

開発合宿一日目は移動がほぼメイン

2010-03-23 14:00

フィルモアを出発
出発時の写真は失念...。

2010-03-23 14:25


上野駅を出発

2010-03-23 14:30


車内で3人で何をつくろっかーで盛り上がる。この先につく駅で愕然とすることも知らず...。

2010-03-23 16:00


埼玉県 深谷に到着

うわー駅がきれー
(でもけっこう殺風景な街なのね...。)

2010-03-23 16:05

合宿の宿を探すため移動。
宿は合宿場所一覧 - kaihachu.com より見つけた きんとう 埼玉 深谷 ビジネスホテル 宴会 懐石 

2010-03-23 16:10

無事チェックインを済まし、部屋へ。


全員おもむろにPCを取り出し、ネット環境のセットアップへ。
一応、pocket wifi を持ってきたけど、無線LAN はホテルのものが利用できたのでそれを利用。
会社へのVPNはPPTPは何故か繋がらなかったけど、L2TPが繋がったのでよしとする。

2010-03-23 16:30

ネットの環境など、一通り終えたので、駅の方面にあったコンビニへ夜食などを買いに移動。

2010-03-23 17:00

コンビニから戻り、開発再開。
もくもく。

2010-03-23 18:45


夜食が出たので、食堂へ。
コース(?)は日本食でした。(写真は食堂にあったふりかけ)

2010-03-23 20:30


椅子とかそういうものはなく、座敷なので、座布団を何枚も重ねながらもくもく。

「冷えピタ」を貼りつつ、もくもく。

2010-03-24 0:30

ブログを書く

明日に続く

まだ続きます...。

2010/03/23

開発合宿なう

ポスト @ 17:47:03 , 修正 @ 2010/03/23 18:04:05 | ,     

我がフィルモアでは、新しいサービスを展開するために開発合宿を行うことになりました!


男3人で開発準備中。(vizooよりもいいサービスを作るぞ!)
※撮影者は僕です

なるべく、開発の様子はなるべくリアルタイムでここで更新できるようにしたいと思いますが、実況は @nowelium または @figit_net にて。

2010/03/08

JNA で mecab

ポスト @ 1:21:07 | , ,     

JNIなmecabを使っていたけど、libmecab(JNI) の *.soとか、*.dylib のコンパイルを環境(LinuxとかMacとか)毎に用意するのが面倒になってきたので、JNAでアクセスできないかと挑戦中...。

mecab.h をよみつつ、こんなインタフェースを用意

package org.chasen.mecab;

import com.sun.jna.Library;
import com.sun.jna.PointerType;
import com.sun.jna.Structure;

public interface LibMecab extends Library {
    
    final int MECAB_NOR_NODE = 0;
    final int MECAB_UNK_NODE = 1;
    final int MECAB_BOS_NODE = 2;
    final int MECAB_EOS_NODE = 3;
    final int MECAB_EON_NODE = 4;
    
    final int MECAB_USR_DIC = 1;
    final int MECAB_SYS_DIC = 0;
    final int MECAB_UNK_DIC = 2;

    int mecab_do(int argc, String...argv);

    mecab_t mecab_new(int argc, String...argv);
    
    mecab_t mecab_new2(final String arg);
    String mecab_version();
    
    String mecab_strerror(mecab_t mecab);
    void mecab_destroy(mecab_t mecab);

    int mecab_get_partial(mecab_t mecab);
    void mecab_set_partial(mecab_t mecab, int partial);
    float mecab_get_theta(mecab_t mecab);
    void mecab_set_theta(mecab_t mecab, float theta);
    int mecab_get_lattice_level(mecab_t mecab);
    void mecab_set_lattice_level(mecab_t mecab, int level);
    int mecab_get_all_morphs(mecab_t mecab);
    void mecab_set_all_morphs(mecab_t mecab, int all_morphs);

    String mecab_sparse_tostr(mecab_t mecab, final String str);
    String mecab_sparse_tostr2(mecab_t mecab, final String str, int len);
    String mecab_sparse_tostr3(mecab_t mecab, final String str, int len, String ostr, int olen);
    mecab_node_t mecab_sparse_tonode(mecab_t mecab, final String chr);
    mecab_node_t mecab_sparse_tonode2(mecab_t mecab, final String chr, int size);
    String mecab_nbest_sparse_tostr(mecab_t mecab, int N, final String str);
    String mecab_nbest_sparse_tostr2(mecab_t mecab, int N, final String str, int len);
    String mecab_nbest_sparse_tostr3(mecab_t mecab, int N, final String str, int len, String ostr, int olen);
    int mecab_nbest_init(mecab_t mecab, final String str);
    int mecab_nbest_init2(mecab_t mecab, final String str, int len);
    String mecab_nbest_next_tostr(mecab_t mecab);
    String mecab_nbest_next_tostr2(mecab_t mecab, String ostr, int olen);
    mecab_node_t mecab_nbest_next_tonode(mecab_t mecab);
    String mecab_format_node(mecab_t mecab, final mecab_node_t node);
    
    mecab_dictionary_info_t mecab_dictionary_info(mecab_t mecab);
    int mecab_dict_index(int argc, String...argv);
    int mecab_dict_gen(int argc, String...argv);
    int mecab_cost_train(int argc, String...argv);
    int mecab_system_eval(int argc, String...argv);
    int mecab_test_gen(int argc, String...argv);
    
    class mecab_t extends PointerType {
        public static class Type extends Structure {
            public int allocated;
        }
        public Type get(){
            Type type = (Type) Structure.newInstance(Type.class);
            type.writeField("allocated", getPointer().getInt(0));
            return type;
        }
    }
    class mecab_node_t extends PointerType {
    }
    class mecab_dictionary_info_t extends PointerType {
    }
    
    abstract class Tagger extends PointerType {
        abstract String parse(final String str);
        abstract Node parseToNode(final String str);
        abstract String parseNBest(int N, final String str);
        abstract boolean parseNBestInit(final String str);
        abstract Node nextNode();
        abstract String next();
        abstract String formatNode(final Node node);

        // configuration
        abstract boolean partial();
        abstract void set_partial(boolean partial);
        abstract float theta();
        abstract void set_theta(float theta);
        abstract int lattice_level();
        abstract void set_lattice_level(int level);
        abstract boolean all_morphs();
        abstract void set_all_morphs(boolean all_morphs);
        
        abstract DictionaryInfo dictionary_info();
        abstract String what();

        static Tagger create(int argc, String...argv){
            return null;
        }
        static Tagger create(String...argv){
            return null;
        }
    }
    
    class Node extends PointerType {
        
    }
    
    class DictionaryInfo extends PointerType {
        
    }
}

で、いざ実行...。

package org.chasen.mecab;

import org.chasen.mecab.LibMecab.mecab_t;

import com.sun.jna.Native;

public class Main {
    public static void main(String...args){
        LibMecab mecab = (LibMecab) Native.loadLibrary("mecab", LibMecab.class);
        System.out.println(mecab.mecab_version());
        
        mecab_t _ = mecab.mecab_new2("");
        System.out.println(mecab.mecab_strerror(_));
        
        // 文字化けだし、動かない...
        String result = mecab.mecab_sparse_tostr(_, "こんにちは!");
        System.out.println(result);
        mecab.mecab_destroy(_);
    }
}

こんな結果は出た。バージョンはちゃんと取れてた。けど、ちゃんと動かない...。

0.97

?	M
??	t
???	d
?ち	t
?	M
??	t
??	d
EOS

うーん。もう少し。。これができれば結構楽になるハズ...。
継続していきます
ref - http://github.com/nowelium/JNA-Mecab

以前のログ