osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #include <osgEarthSymbology/SLD> 00020 #include <osgEarthSymbology/CssUtils> 00021 #include <osgEarthSymbology/Style> 00022 #include <osgEarthSymbology/Expression> 00023 #include <osgEarth/XmlUtils> 00024 #include <stack> 00025 #include <algorithm> 00026 00027 using namespace osgEarth; 00028 using namespace osgEarth::Symbology; 00029 00030 #define CSS_STROKE "stroke" 00031 #define CSS_STROKE_WIDTH "stroke-width" 00032 #define CSS_STROKE_OPACITY "stroke-opacity" 00033 #define CSS_STROKE_LINECAP "stroke-linecap" 00034 00035 #define CSS_FILL "fill" 00036 #define CSS_FILL_OPACITY "fill-opacity" 00037 00038 #define CSS_POINT_SIZE "point-size" 00039 00040 #define CSS_TEXT_FONT "text-font" 00041 #define CSS_TEXT_SIZE "text-size" 00042 #define CSS_TEXT_HALO "text-halo" 00043 #define CSS_TEXT_ATTRIBUTE "text-attribute" 00044 #define CSS_TEXT_ROTATE_TO_SCREEN "text-rotate-to-screen" 00045 #define CSS_TEXT_SIZE_MODE "text-size-mode" 00046 #define CSS_TEXT_REMOVE_DUPLICATE_LABELS "text-remove-duplicate-labels" 00047 #define CSS_TEXT_LINE_ORIENTATION "text-line-orientation" 00048 #define CSS_TEXT_LINE_PLACEMENT "text-line-placement" 00049 #define CSS_TEXT_CONTENT "text-content" 00050 #define CSS_TEXT_CONTENT_ATTRIBUTE_DELIMITER "text-content-attribute-delimiter" 00051 00052 00053 static void 00054 parseLineCap( const std::string& value, optional<Stroke::LineCapStyle>& cap ) 00055 { 00056 if ( value == "butt" ) cap = Stroke::LINECAP_BUTT; 00057 if ( value == "round" ) cap = Stroke::LINECAP_ROUND; 00058 if ( value == "square" ) cap = Stroke::LINECAP_SQUARE; 00059 } 00060 00061 bool 00062 SLDReader::readStyleFromCSSParams( const Config& conf, Style& sc ) 00063 { 00064 sc.setName( conf.key() ); 00065 00066 LineSymbol* line = 0L; 00067 PolygonSymbol* polygon = 0L; 00068 PointSymbol* point = 0L; 00069 TextSymbol* text = 0L; 00070 ExtrusionSymbol* extrusion = 0L; 00071 MarkerSymbol* marker = 0L; 00072 AltitudeSymbol* altitude = 0L; 00073 SkinSymbol* skin = 0L; 00074 00075 for(Properties::const_iterator p = conf.attrs().begin(); p != conf.attrs().end(); p++ ) 00076 { 00077 // ..... LineSymbol ..... 00078 00079 if ( p->first == CSS_STROKE ) 00080 { 00081 if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); 00082 line->stroke()->color() = htmlColorToVec4f( p->second ); 00083 } 00084 else if ( p->first == CSS_STROKE_OPACITY ) 00085 { 00086 if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); 00087 line->stroke()->color().a() = as<float>( p->second, 1.0f ); 00088 } 00089 else if ( p->first == CSS_STROKE_WIDTH ) 00090 { 00091 if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); 00092 line->stroke()->width() = as<float>( p->second, 1.0f ); 00093 } 00094 else if ( p->first == CSS_STROKE_LINECAP ) 00095 { 00096 if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); 00097 parseLineCap( p->second, line->stroke()->lineCap() ); 00098 } 00099 00100 // ..... PolygonSymbol ..... 00101 00102 else if ( p->first == CSS_FILL ) 00103 { 00104 if (!polygon) polygon = sc.getOrCreateSymbol<PolygonSymbol>(); 00105 polygon->fill()->color() = htmlColorToVec4f( p->second ); 00106 00107 if ( !point ) point = sc.getOrCreateSymbol<PointSymbol>(); 00108 point->fill()->color() = htmlColorToVec4f( p->second ); 00109 00110 if ( !text ) text = new TextSymbol(); 00111 text->fill()->color() = htmlColorToVec4f( p->second ); 00112 } 00113 else if ( p->first == CSS_FILL_OPACITY ) 00114 { 00115 if (!polygon) polygon = sc.getOrCreateSymbol<PolygonSymbol>(); 00116 polygon->fill()->color().a() = as<float>( p->second, 1.0f ); 00117 00118 if ( !point ) point = sc.getOrCreateSymbol<PointSymbol>(); 00119 point->fill()->color().a() = as<float>( p->second, 1.0f ); 00120 00121 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00122 text->fill()->color().a() = as<float>( p->second, 1.0f ); 00123 } 00124 00125 // ..... PointSymbol ..... 00126 00127 else if (p->first == CSS_POINT_SIZE) 00128 { 00129 if ( !point ) point = sc.getOrCreateSymbol<PointSymbol>(); 00130 point->size() = as<float>(p->second, 1.0f); 00131 } 00132 00133 // ..... TextSymbol ..... 00134 00135 else if (p->first == CSS_TEXT_SIZE) 00136 { 00137 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00138 text->size() = as<float>(p->second, 32.0f); 00139 } 00140 else if (p->first == CSS_TEXT_FONT) 00141 { 00142 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00143 text->font() = p->second; 00144 } 00145 else if (p->first == CSS_TEXT_HALO) 00146 { 00147 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00148 text->halo()->color() = htmlColorToVec4f( p->second ); 00149 } 00150 //else if (p->first == CSS_TEXT_ATTRIBUTE) 00151 //{ 00152 // if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00153 // text->attribute() = p->second; 00154 //} 00155 else if (p->first == CSS_TEXT_ROTATE_TO_SCREEN) 00156 { 00157 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00158 if (p->second == "true") text->rotateToScreen() = true; 00159 else if (p->second == "false") text->rotateToScreen() = false; 00160 } 00161 else if (p->first == CSS_TEXT_SIZE_MODE) 00162 { 00163 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00164 if (p->second == "screen") text->sizeMode() = TextSymbol::SIZEMODE_SCREEN; 00165 else if (p->second == "object") text->sizeMode() = TextSymbol::SIZEMODE_OBJECT; 00166 } 00167 else if (p->first == CSS_TEXT_REMOVE_DUPLICATE_LABELS) 00168 { 00169 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00170 if (p->second == "true") text->removeDuplicateLabels() = true; 00171 else if (p->second == "false") text->removeDuplicateLabels() = false; 00172 } 00173 else if (p->first == CSS_TEXT_LINE_ORIENTATION) 00174 { 00175 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00176 if (p->second == "parallel") text->lineOrientation() = TextSymbol::LINEORIENTATION_PARALLEL; 00177 else if (p->second == "horizontal") text->lineOrientation() = TextSymbol::LINEORIENTATION_HORIZONTAL; 00178 else if (p->second == "perpendicular") text->lineOrientation() = TextSymbol::LINEORIENTATION_PERPENDICULAR; 00179 } 00180 else if (p->first == CSS_TEXT_LINE_PLACEMENT) 00181 { 00182 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00183 if (p->second == "centroid") text->linePlacement() = TextSymbol::LINEPLACEMENT_CENTROID; 00184 else if (p->second == "along-line") text->linePlacement() = TextSymbol::LINEPLACEMENT_ALONG_LINE; 00185 } 00186 else if (p->first == "text-content") 00187 { 00188 if (!text) text = sc.getOrCreate<TextSymbol>(); 00189 text->content() = StringExpression( p->second ); 00190 } 00191 else if (p->first == "text-priority") 00192 { 00193 if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); 00194 text->priority() = NumericExpression( p->second ); 00195 } 00196 else if (p->first == "text-provider") 00197 { 00198 if (!text) text = sc.getOrCreate<TextSymbol>(); 00199 text->provider() = p->second; 00200 } 00201 00202 // ..... MarkerSymbol ..... 00203 00204 else if (p->first == "marker") 00205 { 00206 if (!marker) marker = sc.getOrCreate<MarkerSymbol>(); 00207 marker->url() = p->second; 00208 marker->url()->setURIContext( conf.uriContext() ); 00209 } 00210 else if (p->first == "marker-placement") 00211 { 00212 if (!marker) marker = sc.getOrCreate<MarkerSymbol>(); 00213 if (p->second == "vertex") marker->placement() = MarkerSymbol::PLACEMENT_VERTEX; 00214 else if (p->second == "interval") marker->placement() = MarkerSymbol::PLACEMENT_INTERVAL; 00215 else if (p->second == "random" ) marker->placement() = MarkerSymbol::PLACEMENT_RANDOM; 00216 else if (p->second == "centroid") marker->placement() = MarkerSymbol::PLACEMENT_CENTROID; 00217 } 00218 else if (p->first == "marker-density") 00219 { 00220 if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); 00221 marker->density() = as<float>(p->second, 1.0f); 00222 } 00223 else if (p->first == "marker-random-seed") 00224 { 00225 if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); 00226 marker->randomSeed() = as<unsigned>(p->second, 0); 00227 } 00228 else if (p->first == "marker-scale") 00229 { 00230 if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); 00231 marker->scale() = NumericExpression(p->second); 00232 } 00233 00234 // ..... ExtrusionSymbol ..... 00235 00236 else if (p->first == "extrusion-height") 00237 { 00238 if (!extrusion) extrusion = sc.getOrCreate<ExtrusionSymbol>(); 00239 extrusion->heightExpression() = NumericExpression(p->second); 00240 } 00241 else if (p->first == "extrusion-flatten") 00242 { 00243 if (!extrusion) extrusion = sc.getOrCreate<ExtrusionSymbol>(); 00244 extrusion->flatten() = as<bool>(p->second, true); 00245 } 00246 else if (p->first == "extrusion-wall-style") 00247 { 00248 if (!extrusion) extrusion = sc.getOrCreate<ExtrusionSymbol>(); 00249 extrusion->wallStyleName() = p->second; 00250 } 00251 else if (p->first == "extrusion-roof-style") 00252 { 00253 if (!extrusion) extrusion = sc.getOrCreate<ExtrusionSymbol>(); 00254 extrusion->roofStyleName() = p->second; 00255 } 00256 00257 // ..... AltitideSymbol ..... 00258 00259 else if (p->first == "altitude-clamping") 00260 { 00261 if (!altitude) altitude = sc.getOrCreateSymbol<AltitudeSymbol>(); 00262 if (p->second == "none" ) altitude->clamping() = AltitudeSymbol::CLAMP_NONE; 00263 else if (p->second == "terrain" ) altitude->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; 00264 else if (p->second == "absolute") altitude->clamping() = AltitudeSymbol::CLAMP_ABSOLUTE; 00265 else if (p->second == "relative") altitude->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN; 00266 } 00267 else if (p->first == "altitude-resolution") 00268 { 00269 if (!altitude) altitude = sc.getOrCreate<AltitudeSymbol>(); 00270 altitude->clampingResolution() = as<float>( p->second, 0.0f ); 00271 } 00272 else if (p->first == "altitude-offset") 00273 { 00274 if (!altitude) altitude = sc.getOrCreate<AltitudeSymbol>(); 00275 altitude->verticalOffset() = NumericExpression( p->second ); 00276 } 00277 else if (p->first == "altitude-scale") 00278 { 00279 if (!altitude) altitude = sc.getOrCreate<AltitudeSymbol>(); 00280 altitude->verticalScale() = NumericExpression( p->second ); 00281 } 00282 00283 // ..... SkinSymbol ..... 00284 00285 else if (p->first == "skin-library") 00286 { 00287 if (!skin) skin = sc.getOrCreate<SkinSymbol>(); 00288 if ( !p->second.empty() ) skin->libraryName() = p->second; 00289 } 00290 else if (p->first == "skin-tags") 00291 { 00292 if (!skin) skin = sc.getOrCreate<SkinSymbol>(); 00293 skin->addTags( p->second ); 00294 } 00295 else if (p->first == "skin-tiled") 00296 { 00297 if (!skin) skin = sc.getOrCreate<SkinSymbol>(); 00298 skin->isTiled() = as<bool>( p->second, false ); 00299 } 00300 else if (p->first == "skin-object-height") 00301 { 00302 if (!skin) skin = sc.getOrCreate<SkinSymbol>(); 00303 skin->objectHeight() = as<float>( p->second, 0.0f ); 00304 } 00305 else if (p->first == "skin-min-object-height") 00306 { 00307 if (!skin) skin = sc.getOrCreate<SkinSymbol>(); 00308 skin->minObjectHeight() = as<float>( p->second, 0.0f ); 00309 } 00310 else if (p->first == "skin-max-object-height") 00311 { 00312 if (!skin) skin = sc.getOrCreate<SkinSymbol>(); 00313 skin->maxObjectHeight() = as<float>( p->second, 0.0f ); 00314 } 00315 else if (p->first == "skin-random-seed") 00316 { 00317 if (!skin) skin = sc.getOrCreate<SkinSymbol>(); 00318 skin->randomSeed() = as<unsigned>( p->second, 0u ); 00319 } 00320 00321 } 00322 00323 return true; 00324 } 00325 00326