вторник, 8 ноября 2011 г.

Создание PDF из карты GeoServer с русским текстом

Я установил printing-plugin в GeoServer из рекомендованной ссылки. Настроил config.yaml
fonts:
  - /usr/share/fonts/PingWin/PWTVerdeTST.ttf
  
        items:
        - !text
          text: 'Заголовок'
          font: PWTVerdeTST
          fontSize: 14
          fontEncoding: Identity-H
Всё работает, как положено. Но мне понадобилось передавать строку текста с клиента. Я заменил
text: 'Заголовок'
на
text: '${mapTitle}'
и вместо русских букв получил нечитаемые символы. При разработке приложения я использую smartgwt. Я нашёл решение этой задачи. В файле config.yaml я убрал
fontEncoding: Identity-H
В приложении я кодирую русский текст из UTF-8 в ANSI.
        // Печать текущего фрагмента карты
        MenuItem printItem = new MenuItem("Печать", skinImageDir + "print.png");
        printItem.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(MenuItemClickEvent event) {
                // Печать текущего фрагмента карты в PDF файл
                Map map = mainTabSet.getMap();
                String geoserverWMS = mainTabSet.getGeoserverWMS(); // http://localhost:8080/geoserver/wms
                String[] urlParts = geoserverWMS.split("(://|:|/)");

                UrlBuilder ub = new UrlBuilder();
                ub.setProtocol(urlParts[0]); //http
                ub.setHost(urlParts[1]); //localhost
                try {
                    ub.setPort(Integer.parseInt(urlParts[2])); //8080
                } catch (NumberFormatException e) {
                    e.printStackTrace(); // UrlBuilder.PORT_UNSPECIFIED
                }
                ub.setPath("/geoserver/pdf/print.pdf");
                java.util.Map params = new java.util.HashMap();
                params.put("units", "\"m\"");
                params.put("srs", "\"" + map.getProjection() + "\"");
                params.put("layout", "\"A4 portrait\"");
                params.put("dpi", "100");
                params.put("mapTitle", "\"Заголовок\"");
                params.put("comment", "\"Комментарий\"");
                params.put("baseURL", "\"" + geoserverWMS + "\"");
                params.put("opacity", "1");
                params.put("singleTile", "true");
                params.put("type", "\"WMS\"");
                params.put("format", "\"image/png\"");
                params.put("center", "["+map.getCenter().lon()+","+map.getCenter().lat()+"]");
                params.put("scale", Long.toString(Math.round(map.getScale())));
                params.put("rotation", "0");

                StringBuilder spec = new StringBuilder();
                spec.append("{");
                spec.append("\"units\":");       spec.append(params.get("units"));
                spec.append(",\"srs\":");        spec.append(params.get("srs"));
                spec.append(",\"layout\":");     spec.append(params.get("layout"));
                spec.append(",\"dpi\":");        spec.append(params.get("dpi"));
                spec.append(",\"mapTitle\":");   spec.append(params.get("mapTitle"));
                spec.append(",\"comment\":");    spec.append(params.get("comment"));
                spec.append(",\"layers\":");
                spec.append("[{\"baseURL\":");   spec.append(params.get("baseURL"));
                spec.append(",\"opacity\":");    spec.append(params.get("opacity"));
                spec.append(",\"singleTile\":"); spec.append(params.get("singleTile"));
                spec.append(",\"type\":");       spec.append(params.get("type"));
                spec.append(",\"layers\":");
                spec.append("[\"egko\"");
                // Получение списка включенных слоёв
                String[] s1 = mainTabSet.getArrayVisibledLayers();
                for (String s : s1)
                    if (s.equals("tp") || s.equals("rp") || s.equals("sp"))
                        spec.append(",\"rptp:main\"");
                    else {
                        spec.append(",\"rptp:");
                        spec.append(s);
                        spec.append("\"");
                    }
                spec.append("]");
                spec.append(",\"format\":");     spec.append(params.get("format"));
                spec.append(",\"styles\":");
                spec.append("[\"\"");
                for (String s : s1)
                    if (s.equals("collector_well"))
                        spec.append(",\"\"");
                    else {
                        spec.append(",\"");
                        if (s.equals("tp") || s.equals("rp") || s.equals("sp"))
                            spec.append("main_");
                        spec.append(s);
                        spec.append("\"");
                    }
                spec.append("]}]");
                spec.append(",\"pages\":");
                spec.append("[{\"center\":");   spec.append(params.get("center"));
                spec.append(",\"scale\":");     spec.append(params.get("scale"));
                spec.append(",\"rotation\":");  spec.append(params.get("rotation"));
                spec.append("}]}");
                String specVal = encodeToAnsi(spec.toString());
                ub.setParameter("spec", specVal);
                String url = URL.decode(ub.buildString());
                Window.open(url, "_top", "");
            }
        });
Здесь русский текст содержится в параметрах mapTitle и comment. Для кодирования русского текста я добавил функцию
    private native static String encodeToAnsi(String str)/*-{
        // UTF-8 to Ansi character encoding
        var hexChars = "0123456789ABCDEF";
        var trans = [];
        for (var i = 1040; i <= 1103; i++)
            trans[i] = "%" + hexChars.charAt((i >> 4) - 53) +
                    hexChars.charAt(i & 0xF); // А-Я,а-я
        trans[1025] = "%A8";      // Ё
        trans[1105] = "%B8";      // ё
        var ret = "";
        for (var i = 0; i < str.length; i++) {
            var code = str.charCodeAt(i);
            if (typeof trans[code] != 'undefined')
                ret += trans[code];
            else
                ret += str.charAt(i);
        }
        return ret;
    }-*/;
Теперь русские буквы правильно отображаются в PDF:

Комментариев нет:

Отправить комментарий