diff --git a/.gitignore b/.gitignore index 1da77f7c9..5d2536c3e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,8 @@ tests/data/sqlite/*index demo/c++/cairo-demo.pdf demo/c++/cairo-demo.png demo/c++/cairo-demo256.png +demo/c++/demo.tif demo/c++/demo.jpg demo/c++/demo.png demo/c++/demo256.png - +tests/cpp_tests/*-bin diff --git a/CHANGELOG b/CHANGELOG.md similarity index 88% rename from CHANGELOG rename to CHANGELOG.md index 8dfa52f59..19b01ad12 100644 --- a/CHANGELOG +++ b/CHANGELOG.md @@ -1,8 +1,4 @@ -# $Id: CHANGELOG 776 2008-12-7 01:30:27Z dane $ - ----------------- -Mapnik Changelog ----------------- +# Mapnik Changelog A simple log of core changes affecting Mapnik usage. @@ -11,10 +7,21 @@ Developers: Please commit along with changes. For a complete change history, see the SVN log. -Mapnik 2.1.0 ------------- +## Mapnik 2.1.0 -- Removed mutex locking during reprojection if using >= proj 4.7 (#1072) +- GDAL: allow setting nodata value on the fly (will override value if nodata is set in data) (#1161) + +- GDAL: respect nodata for paletted/colormapped images (#1160) + +- PostGIS: Added a new option called 'autodetect_key_field' (by default false) that if true will + trigger autodetection of a given tables' primary key allowing for feature.id() to represent + globally unique ids. This option has no effect if the user has not manually supplied the 'key_field' option. (#804) + +- Cairo: Add full rendering support for markers to match AGG renderer functionality (#1071) + +- Fix Markers rendering so that ellipse height/width units are pixels (previously were unintentionally radii) (#1134) + +- Added 'ignore-placement` attribute to markers-symbolizer (#1135) - Removed PointDatasource - use more robust MemoryDatasource instead (#1032) @@ -26,11 +33,47 @@ Mapnik 2.1.0 - Added parameter in OGR plugin to select a layer by SQL query (besides name or index): see http://www.gdal.org/ogr/ogr_sql.html for specifications (kunitoki) (#472) -- Added suppport for output maps as tiff files (addresses #967 partially) +- Added support for output maps as tiff files (addresses #967 partially) + +- Added support for justify-alignment=auto. This is the new default. (#1125) -Mapnik 2.0.0 ------------- +## Mapnik 2.0.1 + +(Packaged from 5cd3cb2efdaf7e9990a57e8e00b652a81aaa39ae) + +- Support for PostGIS 2.0 (#956,#1083) + +- Switched back to "libmapnik" and "import mapnik" rather than "mapnik2" (mapnik2 will still work from python) (#941) + +- Restored Python 2.5 compatibility (#904) + +- Fixed `mapnik-config --version` (#903) + +- Cairo: Add full rendering support for markers to match AGG renderer functionality (#1071) + +- Fix Markers rendering so that ellipse height/width units are pixels (previously were unintentially radii) (#1134) + +- Added 'ignore-placement` attribute to markers-symbolizer (#1135) + +- Removed svn_revision info from mapnik-config and python bindings as git is now used + +- Removed OGCServer from core - now at https://github.com/mapnik/OGCServer (e7f6267) + +- Fixed SQLite open stability across platforms/versions (#854) + +- Workaround for boost interprocess compile error with recent gcc versions (#950,#1001,#1082) + +- Fix possible memory corruption when using hextree mode for png color reduction (#1087) + +- Fixed bug in shield line placement when dx/dy are used to shift the label relative to the placement point (Matt Amos) (#908) + +- Fix to avoid modifying a feature if an attribute is requested that does not exist (0f5ab18ed) + +- Fixed ability to save to jpeg format from python (7387afd9) (#896) + + +## Mapnik 2.0.0 - Add minimum-path-length property to text_symbolizer to allow labels to be placed only on lines of a certain length (#865) @@ -119,8 +162,7 @@ Mapnik 2.0.0 - Implement MarkersSymbolizer in Cairo render and improve the markers placement finder. (#553) -Mapnik 0.7.2 Release --------------------- +# Mapnik 0.7.2 Release - Added forward compatibility for Mapnik 2.0 XML syntax (https://trac.mapnik.org/wiki/Mapnik2/Changes) @@ -163,8 +205,7 @@ Mapnik 0.7.2 Release - Fixed reading of label_position_tolerance on text_symbolizer and height for building_symbolizer -Mapnik 0.7.0 Release --------------------- +# Mapnik 0.7.0 Release (Packaged from r1574) @@ -203,13 +244,13 @@ Mapnik 0.7.0 Release * Valid Usages include: - - (Select ST_Union(geom) as geom from table where ST_Intersects(geometry,!bbox!)) as map - + + (Select ST_Union(geom) as geom from table where ST_Intersects(geometry,!bbox!)) as map + - - (Select * from table where geom && !bbox!) as map - + + (Select * from table where geom && !bbox!) as map + - PostGIS Plugin: Added 'scale_denominator' substitution ability in sql query string (#415/#465) @@ -305,8 +346,7 @@ Mapnik 0.7.0 Release -Mapnik 0.6.1 Release --------------------- +# Mapnik 0.6.1 Release (Packaged from r1247) @@ -390,8 +430,7 @@ Mapnik 0.6.1 Release -Mapnik 0.6.0 Release --------------------- +# Mapnik 0.6.0 Release (Packaged from r1066) diff --git a/Makefile b/Makefile index 51a2abbab..cd956cedc 100755 --- a/Makefile +++ b/Makefile @@ -18,6 +18,13 @@ uninstall: python scons/scons.py uninstall test: + @echo "*** Running visual tests…" + @python tests/visual_tests/test.py -q + @echo "*** Running C++ tests..." + @for FILE in tests/cpp_tests/*-bin; do \ + $${FILE}; \ + done + @echo "*** Running python tests..." @python tests/run_tests.py -q pep8: @@ -26,4 +33,9 @@ pep8: @pep8 -r --select=W293 -q --filename=*.py `pwd`/tests/ | xargs gsed -i 's/^[ \r\t]*$//' @pep8 -r --select=W391 -q --filename=*.py `pwd`/tests/ | xargs gsed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' +grind: + @for FILE in tests/cpp_tests/*-bin; do \ + valgrind --leak-check=full --log-fd=1 $${FILE} | grep definitely; \ + done + .PHONY: clean reset uninstall test install diff --git a/SConstruct b/SConstruct index 28d3cb94f..30930b7f8 100644 --- a/SConstruct +++ b/SConstruct @@ -15,8 +15,6 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -# $Id$ import os @@ -325,7 +323,7 @@ opts.AddVariables( # Variables affecting rendering back-ends BoolVariable('RENDERING_STATS', 'Output rendering statistics during style processing', 'False'), - + BoolVariable('INTERNAL_LIBAGG', 'Use provided libagg', 'True'), BoolVariable('SVG_RENDERER', 'build support for native svg renderer', 'False'), @@ -345,7 +343,12 @@ opts.AddVariables( PathVariable('SQLITE_LIBS', 'Search path for SQLITE library files', '/usr/' + LIBDIR_SCHEMA, PathVariable.PathAccept), PathVariable('RASTERLITE_INCLUDES', 'Search path for RASTERLITE include files', '/usr/include/', PathVariable.PathAccept), PathVariable('RASTERLITE_LIBS', 'Search path for RASTERLITE library files', '/usr/' + LIBDIR_SCHEMA, PathVariable.PathAccept), - + + # Variables for logging and statistics + BoolVariable('ENABLE_LOG', 'Enable logging, which is enabled by default when building in *debug*', 'False'), + BoolVariable('ENABLE_STATS', 'Enable global statistics during map processing', 'False'), + ('LOG_FORMAT_STRING', 'The format string used before log output string, piped through strftime (max length of 255 characters)', 'Mapnik LOG> %Y-%m-%d %H:%M:%S:'), + # Other variables BoolVariable('SHAPE_MEMORY_MAPPED_FILE', 'Utilize memory-mapped files in Shapefile Plugin (higher memory usage, better performance)', 'True'), ('SYSTEM_FONTS','Provide location for python bindings to register fonts (if given aborts installation of bundled DejaVu fonts)',''), @@ -359,7 +362,7 @@ opts.AddVariables( EnumVariable('THREADING','Set threading support','multi', ['multi','single']), EnumVariable('XMLPARSER','Set xml parser','libxml2', ['libxml2','ptree']), ('JOBS', 'Set the number of parallel compilations', "1", lambda key, value, env: int(value), int), - BoolVariable('DEMO', 'Compile demo c++ application', 'False'), + BoolVariable('DEMO', 'Compile demo c++ application', 'True'), BoolVariable('PGSQL2SQLITE', 'Compile and install a utility to convert postgres tables to sqlite', 'False'), BoolVariable('COLOR_PRINT', 'Print build status information in color', 'True'), BoolVariable('SAMPLE_INPUT_PLUGINS', 'Compile and install sample plugins', 'False'), @@ -768,7 +771,7 @@ def GetMapnikLibVersion(context): int main() { - std::cout << MAPNIK_VERSION << std::endl; + std::cout << MAPNIK_VERSION_STRING << std::endl; return 0; } @@ -778,11 +781,7 @@ int main() context.Result(ret[0]) if not ret[1]: return [] - version = int(ret[1].strip()) - patch_level = version % 100 - minor_version = version / 100 % 1000 - major_version = version / 100000 - return [major_version,minor_version,patch_level] + return ret[1].strip() def icu_at_least_four_two(context): ret = context.TryRun(""" @@ -814,6 +813,9 @@ int main() return False def boost_regex_has_icu(context): + if env['RUNTIME_LINK'] == 'static': + context.env.Append(LIBS='icui18n') + context.env.Append(LIBS='icudata') ret = context.TryRun(""" #include @@ -1072,7 +1074,7 @@ if not preconfigured: # libxml2 should be optional but is currently not # https://github.com/mapnik/mapnik/issues/913 - if conf.parse_config('XML2_CONFIG'): + if conf.parse_config('XML2_CONFIG',checks='--cflags'): env['HAS_LIBXML2'] = True LIBSHEADERS = [ @@ -1164,7 +1166,7 @@ if not preconfigured: env.Append(CXXFLAGS = '-DBOOST_REGEX_HAS_ICU') else: env['SKIPPED_DEPS'].append('boost_regex_icu') - + env['REQUESTED_PLUGINS'] = [ driver.strip() for driver in Split(env['INPUT_PLUGINS'])] if len(env['REQUESTED_PLUGINS']): @@ -1382,14 +1384,13 @@ if not preconfigured: # fetch the mapnik version header in order to set the # ABI version used to build libmapnik.so on linux in src/build.py abi = conf.GetMapnikLibVersion() - abi_fallback = [2,0,0] + abi_fallback = "2.0.1-pre" if not abi: color_print(1,'Problem encountered parsing mapnik version, falling back to %s' % abi_fallback) - env['ABI_VERSION'] = abi_fallback - else: - env['ABI_VERSION'] = abi - env['MAPNIK_VERSION_STRING'] = '.'.join(['%d' % i for i in env['ABI_VERSION']]) + abi = abi_fallback + env['ABI_VERSION'] = abi.replace('-pre','').split('.') + env['MAPNIK_VERSION_STRING'] = abi # Common C++ flags. if env['THREADING'] == 'multi': @@ -1411,10 +1412,29 @@ if not preconfigured: pthread = '-pthread' # Common debugging flags. - debug_flags = '-g -DDEBUG -DMAPNIK_DEBUG' + # http://lists.fedoraproject.org/pipermail/devel/2010-November/144952.html + debug_flags = '-g -fno-omit-frame-pointer -DDEBUG -DMAPNIK_DEBUG' ndebug_flags = '-DNDEBUG' - - + + # Enable logging in debug mode (always) and release mode (when specified) + log_enabled = ' -DMAPNIK_LOG -DMAPNIK_LOG_FORMAT="%s"' % env['LOG_FORMAT_STRING'] + + if env['DEBUG']: + debug_flags += log_enabled + else: + if env['ENABLE_LOG']: + ndebug_flags += log_enabled + + # Enable statistics reporting + if env['ENABLE_STATS']: + debug_flags += ' -DMAPNIK_STATS' + ndebug_flags += ' -DMAPNIK_STATS' + + # Add rdynamic to allow using statics between application and plugins + # http://stackoverflow.com/questions/8623657/multiple-instances-of-singleton-across-shared-libraries-on-linux + if env['PLATFORM'] != 'Darwin': + env.MergeFlags('-rdynamic') + # Customizing the C++ compiler flags depending on: # (1) the C++ compiler used; and # (2) whether debug binaries are requested. @@ -1719,7 +1739,7 @@ if not HELP_REQUESTED: # build C++ tests # not ready for release - #SConscript('tests/cpp_tests/build.py') + SConscript('tests/cpp_tests/build.py') # not ready for release #if env['SVG_RENDERER']: diff --git a/bindings/python/mapnik/__init__.py b/bindings/python/mapnik/__init__.py index 423d40199..ff3191d2f 100644 --- a/bindings/python/mapnik/__init__.py +++ b/bindings/python/mapnik/__init__.py @@ -120,7 +120,7 @@ class _Coord(Coord,_injector): Returns the easting (x) and northing (y) as a coordinate pair. - + Example: Project the geographic coordinates of the city center of Stuttgart into the local map projection (GK Zone 3/DHDN, EPSG 31467) @@ -136,7 +136,7 @@ class _Coord(Coord,_injector): into the geographic space. The x component is considered to be the easting, the y component to be the northing. - + Returns the longitude (x) and latitude (y) as a coordinate pair. @@ -153,8 +153,8 @@ class _Coord(Coord,_injector): class _Box2d(Box2d,_injector): """ Represents a spatial envelope (i.e. bounding box). - - + + Following operators are defined for Box2d: Addition: @@ -285,12 +285,12 @@ def Datasource(**keywords): Create a Mapnik Datasource using a dictionary of parameters. Keywords must include: - + type='plugin_name' # e.g. type='gdal' - + See the convenience factory methods of each input plugin for details on additional required keyword arguments. - + """ return CreateDatasource(keywords) @@ -322,7 +322,7 @@ def PostGIS(**keywords): Required keyword arguments: dbname -- database name to connect to table -- table name or subselect query - + *Note: if using subselects for the 'table' value consider also passing the 'geometry_field' and 'srid' and 'extent_from_subquery' options and/or specifying the 'geometry_table' option. @@ -572,13 +572,6 @@ def Geos(**keywords): keywords['type'] = 'geos' return CreateDatasource(keywords) -def mapnik_version_string(version=mapnik_version()): - """Return the Mapnik version as a string.""" - patch_level = version % 100 - minor_version = version / 100 % 1000 - major_version = version / 100000 - return '%s.%s.%s' % ( major_version, minor_version,patch_level) - def mapnik_version_from_string(version_string): """Return the Mapnik version from a string.""" n = version_string.split('.') @@ -599,113 +592,3 @@ def register_fonts(path=fontscollectionpath,valid_extensions=['.ttf','.otf','.tt # auto-register known plugins and fonts register_plugins() register_fonts() - -# Explicitly export API members to avoid namespace pollution -# and ensure correct documentation processing -__all__ = [ - # classes - 'CharProperties', - 'Color', - 'Coord', - 'Palette', - #'ColorBand', - 'CompositeOp', - 'DatasourceCache', - 'MemoryDatasource', - 'Box2d', - 'Feature', - 'Featureset', - 'FontEngine', - 'FontSet', - 'FormattingNode', - 'FormattingText', - 'FormattingFormat', - 'FormattingList', - 'FormattingExpressionFormat', - 'Geometry2d', - 'Image', - 'ImageView', - 'Grid', - 'GridView', - 'Layer', - 'Layers', - 'LinePatternSymbolizer', - 'LineSymbolizer', - 'Map', - 'MarkersSymbolizer', - 'Names', - 'Path', - 'Parameter', - 'Parameters', - 'PointSymbolizer', - 'PolygonPatternSymbolizer', - 'PolygonSymbolizer', - 'ProcessedText', - 'ProjTransform', - 'Projection', - 'Query', - 'RasterSymbolizer', - 'RasterColorizer', - 'Rule', 'Rules', - 'ShieldSymbolizer', - 'Singleton', - 'Stroke', - 'Style', - 'Symbolizer', - 'Symbolizers', - 'TextPlacements', - 'TextPlacementInfo', - 'TextSymbolizer', - 'TextSymbolizerProperties', - 'ViewTransform', - # enums - 'aspect_fix_mode', - 'point_placement', - 'label_placement', - 'line_cap', - 'line_join', - 'text_transform', - 'vertical_alignment', - 'horizontal_alignment', - 'justify_alignment', - 'pattern_alignment', - 'filter_mode', - # functions - # datasources - 'Datasource', - 'CreateDatasource', - 'Shapefile', - 'PostGIS', - 'Raster', - 'Gdal', - 'Occi', - 'Ogr', - 'SQLite', - 'Osm', - 'Kismet', - # version and environment - 'mapnik_version_string', - 'mapnik_version', - 'has_cairo', - 'has_pycairo', - # factory methods - 'Expression', - 'PathExpression', - # load/save/render - 'load_map', - 'render_stats', - 'load_map_from_string', - 'save_map', - 'save_map_to_string', - 'render', - 'render_grid', - 'render_tile_to_file', - 'render_to_file', - # other - 'register_plugins', - 'register_fonts', - 'scale_denominator', - # deprecated - 'Filter', - 'Envelope', - ] diff --git a/bindings/python/mapnik/printing.py b/bindings/python/mapnik/printing.py index 5e6456bd9..8c15d8a8c 100644 --- a/bindings/python/mapnik/printing.py +++ b/bindings/python/mapnik/printing.py @@ -43,7 +43,7 @@ except ImportError: class centering: """Style of centering to use with the map, the default is constrained - + none: map will be placed flush with the margin/box in the top left corner constrained: map will be centered on the most constrained axis (for a portrait page and a square map this will be horizontally) @@ -167,7 +167,7 @@ def sequence_scale(scale,scale_sequence): """Default scale helper, this rounds scale to a 'sensible' value""" factor = math.floor(math.log10(scale)) norm = scale/(10**factor) - + for s in scale_sequence: if norm <= s: return s*10**factor @@ -199,7 +199,7 @@ def deg_min_sec_scale(scale): return x else: return x - + def format_deg_min_sec(value): deg = math.floor(value) min = math.floor((value-deg)/(1.0/60)) @@ -219,12 +219,12 @@ def convert_pdf_pages_to_layers(filename,output_name=None,layer_names=(),reverse opens the given multipage PDF and converts each page to be a layer in a single page PDF layer_names should be a sequence of the user visible names of the layers, if not given or if shorter than num pages generic names will be given to the unnamed layers - + if output_name is not provided a temporary file will be used for the conversion which will then be copied back over the source file. - + requires pyPdf >= 1.13 to be available""" - + if not HAS_PYPDF: raise Exception("pyPdf Not available") @@ -235,13 +235,13 @@ def convert_pdf_pages_to_layers(filename,output_name=None,layer_names=(),reverse else: (outfd,outfilename) = tempfile.mkstemp(dir=os.path.dirname(filename)) outfile = os.fdopen(outfd,'wb') - + i = pyPdf.PdfFileReader(infile) o = pyPdf.PdfFileWriter() - + template_page_size = i.pages[0].mediaBox op = o.addBlankPage(width=template_page_size.getWidth(),height=template_page_size.getHeight()) - + contentkey = pyPdf.generic.NameObject('/Contents') resourcekey = pyPdf.generic.NameObject('/Resources') propertieskey = pyPdf.generic.NameObject('/Properties') @@ -249,7 +249,7 @@ def convert_pdf_pages_to_layers(filename,output_name=None,layer_names=(),reverse op[resourcekey] = pyPdf.generic.DictionaryObject() properties = pyPdf.generic.DictionaryObject() ocgs = pyPdf.generic.ArrayObject() - + for (i, p) in enumerate(i.pages): # first start an OCG for the layer ocgname = pyPdf.generic.NameObject('/oc%d' % i) @@ -262,9 +262,9 @@ def convert_pdf_pages_to_layers(filename,output_name=None,layer_names=(),reverse p[pyPdf.generic.NameObject('/Contents')].append(ocgend) else: p[pyPdf.generic.NameObject('/Contents')] = pyPdf.generic.ArrayObject((ocgstart,p['/Contents'],ocgend)) - + op.mergePage(p) - + ocg = pyPdf.generic.DictionaryObject() ocg[pyPdf.generic.NameObject('/Type')] = pyPdf.generic.NameObject('/OCG') if len(layer_names) > i: @@ -274,9 +274,9 @@ def convert_pdf_pages_to_layers(filename,output_name=None,layer_names=(),reverse indirect_ocg = o._addObject(ocg) properties[ocgname] = indirect_ocg ocgs.append(indirect_ocg) - + op[resourcekey][propertieskey] = o._addObject(properties) - + ocproperties = pyPdf.generic.DictionaryObject() ocproperties[pyPdf.generic.NameObject('/OCGs')] = ocgs defaultview = pyPdf.generic.DictionaryObject() @@ -289,16 +289,16 @@ def convert_pdf_pages_to_layers(filename,output_name=None,layer_names=(),reverse else: defaultview[pyPdf.generic.NameObject('/Order')] = pyPdf.generic.ArrayObject(reversed(ocgs)) defaultview[pyPdf.generic.NameObject('/OFF')] = pyPdf.generic.ArrayObject() - + ocproperties[pyPdf.generic.NameObject('/D')] = o._addObject(defaultview) - + o._root.getObject()[pyPdf.generic.NameObject('/OCProperties')] = o._addObject(ocproperties) - + o.write(outfile) - + outfile.close() infile.close() - + if not output_name: os.rename(outfilename, filename) @@ -318,7 +318,7 @@ class PDFPrinter: is_latlon=False, use_ocg_layers=False): """Creates a cairo surface and context to render a PDF with. - + pagesize: tuple of page size in meters, see predefined sizes in pagessizes dict (default a4) margin: page margin in meters (default 0.01) box: box within the page to render the map into (will not render over margin). This should be @@ -348,54 +348,54 @@ class PDFPrinter: self._centering = centering self._is_latlon = is_latlon self._use_ocg_layers = use_ocg_layers - + self._s = None self._layer_names = [] self._filename = None - + self.map_box = None self.scale = None - + # don't both to round the scale if they are not preserving the aspect ratio if not preserve_aspect: self._scale = any_scale - + if percent_box: self._box = Box2d(percent_box[0]*pagesize[0],percent_box[1]*pagesize[1], percent_box[2]*pagesize[0],percent_box[3]*pagesize[1]) if not HAS_PYCAIRO_MODULE: raise Exception("PDF rendering only available when pycairo is available") - + self.font_name = "DejaVu Sans" - + def finish(self): if self._s: self._s.finish() self._s = None - + if self._use_ocg_layers: convert_pdf_pages_to_layers(self._filename,layer_names=self._layer_names + ["Legend and Information"],reverse_all_but_last=True) - + def add_geospatial_pdf_header(self,m,filename,epsg=None,wkt=None): """ Postprocessing step to add geospatial PDF information to PDF file as per PDF standard 1.7 extension level 3 (also in draft PDF v2 standard at time of writing) - + one of either the epsg code or wkt text for the projection must be provided - + Should be called *after* the page has had .finish() called""" if HAS_PYPDF and (epsg or wkt): infile=file(filename,'rb') (outfd,outfilename) = tempfile.mkstemp(dir=os.path.dirname(filename)) outfile = os.fdopen(outfd,'wb') - + i=pyPdf.PdfFileReader(infile) o=pyPdf.PdfFileWriter() - + # preserve OCProperties at document root if we have one if i.trailer['/Root'].has_key(pyPdf.generic.NameObject('/OCProperties')): o._root.getObject()[pyPdf.generic.NameObject('/OCProperties')] = i.trailer['/Root'].getObject()[pyPdf.generic.NameObject('/OCProperties')] - + for p in i.pages: gcs = pyPdf.generic.DictionaryObject() gcs[pyPdf.generic.NameObject('/Type')]=pyPdf.generic.NameObject('/PROJCS') @@ -403,7 +403,7 @@ class PDFPrinter: gcs[pyPdf.generic.NameObject('/EPSG')]=pyPdf.generic.NumberObject(int(epsg)) if wkt: gcs[pyPdf.generic.NameObject('/WKT')]=pyPdf.generic.TextStringObject(wkt) - + measure = pyPdf.generic.DictionaryObject() measure[pyPdf.generic.NameObject('/Type')]=pyPdf.generic.NameObject('/Measure') measure[pyPdf.generic.NameObject('/Subtype')]=pyPdf.generic.NameObject('/GEO') @@ -414,7 +414,7 @@ class PDFPrinter: measure[pyPdf.generic.NameObject('/Bounds')]=bounds measure[pyPdf.generic.NameObject('/LPTS')]=bounds gpts=pyPdf.generic.ArrayObject() - + proj=Projection(m.srs) env=m.envelope() for x in ((env.minx, env.miny), (env.minx, env.maxy), (env.maxx, env.maxy), (env.maxx, env.miny)): @@ -423,31 +423,31 @@ class PDFPrinter: gpts.append(pyPdf.generic.FloatObject(str(latlon_corner.y))) gpts.append(pyPdf.generic.FloatObject(str(latlon_corner.x))) measure[pyPdf.generic.NameObject('/GPTS')]=gpts - + vp=pyPdf.generic.DictionaryObject() vp[pyPdf.generic.NameObject('/Type')]=pyPdf.generic.NameObject('/Viewport') bbox=pyPdf.generic.ArrayObject() - + for x in self.map_box: bbox.append(pyPdf.generic.FloatObject(str(x))) vp[pyPdf.generic.NameObject('/BBox')]=bbox vp[pyPdf.generic.NameObject('/Measure')]=measure - + vpa = pyPdf.generic.ArrayObject() vpa.append(vp) p[pyPdf.generic.NameObject('/VP')]=vpa o.addPage(p) - + o.write(outfile) infile=None outfile.close() os.rename(outfilename,filename) - - + + def get_context(self): """allow access so that extra 'bits' can be rendered to the page directly""" return cairo.Context(self._s) - + def get_width(self): return self._pagesize[0] @@ -456,7 +456,7 @@ class PDFPrinter: def get_margin(self): return self._margin - + def write_text(self,ctx,text,box_width=None,size=10, fill_color=(0.0, 0.0, 0.0), alignment=None): if HAS_PANGOCAIRO_MODULE: (attr,t,accel) = pango.parse_markup(text) @@ -474,7 +474,7 @@ class PDFPrinter: pctx.set_source_rgb(*fill_color) pctx.show_layout(l) return l.get_pixel_extents()[0] - + else: ctx.rel_move_to(0,size) ctx.select_font_face(self.font_name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) @@ -489,18 +489,18 @@ class PDFPrinter: elif HAS_PYCAIRO_MODULE: return cairo.Context(self._s) return None - + def _get_render_area(self): """return a bounding box with the area of the page we are allowed to render out map to in page coordinates (i.e. meters) """ # take off our page margins render_area = Box2d(self._margin,self._margin,self._pagesize[0]-self._margin,self._pagesize[1]-self._margin) - + #then if user specified a box to render get intersection with that if self._box: return render_area.intersect(self._box) - + return render_area def _get_render_area_size(self): @@ -513,7 +513,7 @@ class PDFPrinter: available_area = self._get_render_area_size() map_aspect = m.envelope().width()/m.envelope().height() page_aspect = available_area[0]/available_area[1] - + return map_aspect > page_aspect def _get_meta_info_corner(self,render_size,m): @@ -526,7 +526,7 @@ class PDFPrinter: else: x += render_size[0]+0.005 y = self._margin - + return (x,y) def _get_render_corner(self,render_size,m): @@ -535,9 +535,9 @@ class PDFPrinter: x=available_area[0] y=available_area[1] - + h_is_contrained = self._is_h_contrained(m) - + if (self._centering == centering.both or self._centering == centering.horizontal or (self._centering == centering.constrained and h_is_contrained) or @@ -550,26 +550,26 @@ class PDFPrinter: (self._centering == centering.unconstrained and h_is_contrained)): y+=(available_area.height()-render_size[1])/2 return (x,y) - + def _get_map_pixel_size(self, width_page_m, height_page_m): """for a given map size in paper coordinates return a tuple of the map 'pixel' size we should create at the defined resolution""" return (int(m2px(width_page_m,self._resolution)), int(m2px(height_page_m,self._resolution))) - + def render_map(self,m, filename): """Render the given map to filename""" - + # store this for later so we can post process the PDF self._filename = filename - + # work out the best scale to render out map at given the available space (eff_width,eff_height) = self._get_render_area_size() map_aspect = m.envelope().width()/m.envelope().height() page_aspect = eff_width/eff_height - + scalex=m.envelope().width()/eff_width scaley=m.envelope().height()/eff_height - + scale=max(scalex,scaley) rounded_mapscale=self._scale(scale) @@ -581,26 +581,26 @@ class PDFPrinter: maph=mapw*(1/map_aspect) else: mapw=maph*map_aspect - + # set the map size so that raster elements render at the correct resolution m.resize(*self._get_map_pixel_size(mapw,maph)) # calculate the translation for the map starting point (tx,ty) = self._get_render_corner((mapw,maph),m) - + # create our cairo surface and context and then render the map into it self._s = cairo.PDFSurface(filename, m2pt(self._pagesize[0]),m2pt(self._pagesize[1])) ctx=cairo.Context(self._s) - + for l in m.layers: # extract the layer names for naming layers if we use OCG self._layer_names.append(l.name) - + layer_map = Map(m.width,m.height,m.srs) layer_map.layers.append(l) for s in l.styles: layer_map.append_style(s,m.find_style(s)) layer_map.zoom_to_box(m.envelope()) - + def render_map(): ctx.save() ctx.translate(m2pt(tx),m2pt(ty)) @@ -608,7 +608,7 @@ class PDFPrinter: ctx.scale(72.0/self._resolution,72.0/self._resolution) render(layer_map, ctx) ctx.restore() - + # antimeridian render_map() if self._is_latlon and (m.envelope().minx < -180 or m.envelope().maxx > 180): @@ -621,10 +621,10 @@ class PDFPrinter: render_map() # restore the original env m.zoom_to_box(old_env) - + if self._use_ocg_layers: self._s.show_page() - + self.scale = rounded_mapscale self.map_box = Box2d(tx,ty,tx+mapw,ty+maph) @@ -640,7 +640,7 @@ class PDFPrinter: if p2.inverse(m.envelope().center()).y > latlon_bounds.maxy: latlon_bounds = Box2d(latlon_bounds.miny,latlon_bounds.maxy,latlon_bounds.maxx,latlon_bounds.miny+360) - + latlon_mapwidth = latlon_bounds.width() # render an extra 20% so we generally won't miss the ends of lines latlon_buffer = 0.2*latlon_mapwidth @@ -649,7 +649,7 @@ class PDFPrinter: else: latlon_divsize = deg_min_sec_scale(latlon_mapwidth/7.0) latlon_interpsize = latlon_mapwidth/m.width - + self._render_lat_lon_axis(m,p2,latlon_bounds.minx,latlon_bounds.maxx,latlon_bounds.miny,latlon_bounds.maxy,latlon_buffer,latlon_interpsize,latlon_divsize,dec_degrees,True) self._render_lat_lon_axis(m,p2,latlon_bounds.miny,latlon_bounds.maxy,latlon_bounds.minx,latlon_bounds.maxx,latlon_buffer,latlon_interpsize,latlon_divsize,dec_degrees,False) @@ -658,21 +658,21 @@ class PDFPrinter: ctx.set_source_rgb(1,0,0) ctx.set_line_width(1) latlon_labelsize = 6 - + ctx.translate(m2pt(self.map_box.minx),m2pt(self.map_box.miny)) ctx.rectangle(0,0,m2pt(self.map_box.width()),m2pt(self.map_box.height())) ctx.clip() - + ctx.select_font_face("DejaVu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_font_size(latlon_labelsize) - + box_top = self.map_box.height() if not is_x_axis: ctx.translate(m2pt(self.map_box.width()/2),m2pt(self.map_box.height()/2)) ctx.rotate(-math.pi/2) ctx.translate(-m2pt(self.map_box.height()/2),-m2pt(self.map_box.width()/2)) box_top = self.map_box.width() - + for xvalue in round_grid_generator(x1 - latlon_buffer,x2 + latlon_buffer,latlon_divsize): yvalue = y1 - latlon_buffer start_cross = None @@ -693,12 +693,12 @@ class PDFPrinter: ctx.move_to(start.x,start.y) ctx.line_to(end.x,end.y) ctx.stroke() - + if cmp(start.y, 0) != cmp(end.y,0): start_cross = end.x if cmp(start.y,m2pt(self.map_box.height())) != cmp(end.y, m2pt(self.map_box.height())): end_cross = end.x - + if dec_degrees: line_text = "%g" % (xvalue) else: @@ -712,19 +712,19 @@ class PDFPrinter: def render_on_map_scale(self,m): (div_size,page_div_size) = self._get_sensible_scalebar_size(m) - + first_value_x = (math.floor(m.envelope().minx / div_size) + 1) * div_size first_value_x_percent = (first_value_x-m.envelope().minx)/m.envelope().width() self._render_scale_axis(first_value_x,first_value_x_percent,self.map_box.minx,self.map_box.maxx,page_div_size,div_size,self.map_box.miny,self.map_box.maxy,True) - + first_value_y = (math.floor(m.envelope().miny / div_size) + 1) * div_size first_value_y_percent = (first_value_y-m.envelope().miny)/m.envelope().height() self._render_scale_axis(first_value_y,first_value_y_percent,self.map_box.miny,self.map_box.maxy,page_div_size,div_size,self.map_box.minx,self.map_box.maxx,False) - + if self._use_ocg_layers: self._s.show_page() self._layer_names.append("Coordinate Grid Overlay") - + def _get_sensible_scalebar_size(self,m,width=-1): # aim for about 8 divisions across the map # also make sure we can fit the bar with in page area width if specified @@ -744,7 +744,7 @@ class PDFPrinter: ctx.set_source_rgb(*stroke_color) ctx.rectangle(x,y,w,h) ctx.stroke() - + if text: ctx.move_to(x+1,y) self.write_text(ctx,text,fill_color=[1-z for z in fill_color],size=h-2) @@ -758,14 +758,14 @@ class PDFPrinter: label_value = first-div_size if self._is_latlon and label_value < -180: label_value += 360 - + ctx=cairo.Context(self._s) - + if not is_x_axis: ctx.translate(m2pt(self.map_box.center().x),m2pt(self.map_box.center().y)) ctx.rotate(-math.pi/2) ctx.translate(-m2pt(self.map_box.center().y),-m2pt(self.map_box.center().x)) - + while value < end: ctx.move_to(m2pt(value),m2pt(boundary_start)) ctx.line_to(m2pt(value),m2pt(boundary_end)) @@ -775,7 +775,7 @@ class PDFPrinter: for bar in (m2pt(boundary_start)-border_size,m2pt(boundary_end)): self._render_box(ctx,m2pt(prev),bar,m2pt(value-prev),border_size,text,fill_color=fill) - + prev = value value+=page_div_size fill = [1-z for z in fill] @@ -787,18 +787,18 @@ class PDFPrinter: for bar in (m2pt(boundary_start)-border_size,m2pt(boundary_end)): self._render_box(ctx,m2pt(prev),bar,m2pt(end-prev),border_size,fill_color=fill) - + def render_scale(self,m,ctx=None,width=0.05): """ m: map to render scale for ctx: A cairo context to render the scale to. If this is None (the default) then automatically create a context and choose the best location for the scale bar. width: Width of area available to render scale bar in (in m) - + will return the size of the rendered scale block in pts """ - + (w,h) = (0,0) - + # don't render scale if we are lat lon # dont report scale if we have warped the aspect ratio if self._preserve_aspect and not self._is_latlon: @@ -808,15 +808,15 @@ class PDFPrinter: ctx=cairo.Context(self._s) (tx,ty) = self._get_meta_info_corner((self.map_box.width(),self.map_box.height()),m) ctx.translate(tx,ty) - + (div_size,page_div_size) = self._get_sensible_scalebar_size(m, width/box_count) - + div_unit = "m" if div_size > 1000: div_size /= 1000 div_unit = "km" - + text = "0%s" % div_unit ctx.save() if width > 0: @@ -846,7 +846,7 @@ class PDFPrinter: text_ext=self.write_text(ctx,"Scale 1:%d" % self.scale,box_width=box_width,size=font_size, alignment=alignment) h+=text_ext[3]+2 - + return (w,h) def render_legend(self,m, page_break=False, ctx=None, collumns=1,width=None, height=None, item_per_rule=False, attribution={}, legend_item_box_size=(0.015,0.0075)): @@ -858,7 +858,7 @@ class PDFPrinter: collumns: number of collumns available in legend box attribution: additional text that will be rendered in gray under the layer name. keyed by layer name legend_item_box_size: two tuple with width and height of legend item box size in meters - + will return the size of the rendered block in pts """ @@ -879,7 +879,7 @@ class PDFPrinter: else: cwidth = None current_collumn = 0 - + processed_layers = [] for l in reversed(m.layers): have_layer_header = False @@ -888,7 +888,7 @@ class PDFPrinter: if layer_title in processed_layers: continue processed_layers.append(layer_title) - + # check through the features to find which combinations of styles are active # for each unique combination add a legend entry for f in l.datasource.all_features(): @@ -913,20 +913,20 @@ class PDFPrinter: active_rules = tuple(active_rules) if added_styles.has_key(active_rules): continue - + added_styles[active_rules] = (f,rule_text) if not item_per_rule: break else: added_styles[l] = (None,None) - + legend_items = added_styles.keys() legend_items.sort() for li in legend_items: if True: (f,rule_text) = added_styles[li] - - + + legend_map_size = (int(m2pt(legend_item_box_size[0])),int(m2pt(legend_item_box_size[1]))) lemap=Map(legend_map_size[0],legend_map_size[1],srs=m.srs) if m.background: @@ -967,11 +967,11 @@ class PDFPrinter: for s in l.styles: lelayer.styles.append(s) lemap.layers.append(lelayer) - + if f is None or f.envelope().width() != 0: lemap.zoom_all() lemap.zoom(1.1) - + item_size = legend_map_size[1] if not have_layer_header: item_size += 8 @@ -998,7 +998,7 @@ class PDFPrinter: ctx.save() render(lemap, ctx) ctx.restore() - + ctx.rectangle(0,0,*legend_map_size) ctx.set_source_rgb(0.5,0.5,0.5) ctx.set_line_width(1) @@ -1017,12 +1017,12 @@ class PDFPrinter: if attribution.has_key(layer_title): e=self.write_text(ctx, attribution[layer_title], m2pt(cwidth-legend_item_box_size[0]-0.005), 6, fill_color=(0.5,0.5,0.5)) legend_text_size += e[3] - + if legend_text_size > legend_entry_size: legend_entry_size=legend_text_size - + y+=legend_entry_size +2 if y > h: h = y return (w,h) - + diff --git a/bindings/python/mapnik_color.cpp b/bindings/python/mapnik_color.cpp index 1b6e34fb2..82611ff48 100644 --- a/bindings/python/mapnik_color.cpp +++ b/bindings/python/mapnik_color.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_coord.cpp b/bindings/python/mapnik_coord.cpp index 103dad3f8..b9b4e6277 100644 --- a/bindings/python/mapnik_coord.cpp +++ b/bindings/python/mapnik_coord.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_datasource.cpp b/bindings/python/mapnik_datasource.cpp index d7b83040e..f89b4eb01 100644 --- a/bindings/python/mapnik_datasource.cpp +++ b/bindings/python/mapnik_datasource.cpp @@ -19,10 +19,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ + // boost #include #include + // stl #include #include diff --git a/bindings/python/mapnik_datasource_cache.cpp b/bindings/python/mapnik_datasource_cache.cpp index 6b62b7129..c4381837b 100644 --- a/bindings/python/mapnik_datasource_cache.cpp +++ b/bindings/python/mapnik_datasource_cache.cpp @@ -20,8 +20,6 @@ * *****************************************************************************/ -//$Id$ - #include #include diff --git a/bindings/python/mapnik_envelope.cpp b/bindings/python/mapnik_envelope.cpp index 5aa35a0bf..099f319cc 100644 --- a/bindings/python/mapnik_envelope.cpp +++ b/bindings/python/mapnik_envelope.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id: mapnik_envelope.cc 27 2005-03-30 21:45:40Z pavlenko $ // boost #include diff --git a/bindings/python/mapnik_expression.cpp b/bindings/python/mapnik_expression.cpp index d95d5879b..b75281394 100644 --- a/bindings/python/mapnik_expression.cpp +++ b/bindings/python/mapnik_expression.cpp @@ -19,9 +19,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include +#include + // mapnik #include #include @@ -30,7 +32,6 @@ #include #include -#include using mapnik::Feature; using mapnik::expression_ptr; diff --git a/bindings/python/mapnik_feature.cpp b/bindings/python/mapnik_feature.cpp index e55842e26..c4d7f75b6 100644 --- a/bindings/python/mapnik_feature.cpp +++ b/bindings/python/mapnik_feature.cpp @@ -19,13 +19,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost - #include //#include - #include #include #include diff --git a/bindings/python/mapnik_featureset.cpp b/bindings/python/mapnik_featureset.cpp index c7f4722d3..21eb7b796 100644 --- a/bindings/python/mapnik_featureset.cpp +++ b/bindings/python/mapnik_featureset.cpp @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include + // mapnik #include #include diff --git a/bindings/python/mapnik_font_engine.cpp b/bindings/python/mapnik_font_engine.cpp index 3992b1287..5f4160756 100644 --- a/bindings/python/mapnik_font_engine.cpp +++ b/bindings/python/mapnik_font_engine.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include @@ -42,6 +41,7 @@ void export_font_engine() .def("register_fonts",&freetype_engine::register_fonts) .def("face_names",&freetype_engine::face_names) .staticmethod("register_font") + .staticmethod("register_fonts") .staticmethod("face_names") ; } diff --git a/bindings/python/mapnik_geometry.cpp b/bindings/python/mapnik_geometry.cpp index 06aa96207..cd2506628 100644 --- a/bindings/python/mapnik_geometry.cpp +++ b/bindings/python/mapnik_geometry.cpp @@ -17,7 +17,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_grid.cpp b/bindings/python/mapnik_grid.cpp index 2cfce2b7b..95a20efaf 100644 --- a/bindings/python/mapnik_grid.cpp +++ b/bindings/python/mapnik_grid.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_grid_view.cpp b/bindings/python/mapnik_grid_view.cpp index bb39a5b88..926ee18f6 100644 --- a/bindings/python/mapnik_grid_view.cpp +++ b/bindings/python/mapnik_grid_view.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_image.cpp b/bindings/python/mapnik_image.cpp index 858c53437..ff4d17c0b 100644 --- a/bindings/python/mapnik_image.cpp +++ b/bindings/python/mapnik_image.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ extern "C" { @@ -125,7 +124,7 @@ bool painted(mapnik::image_32 const& im) void set_pixel(mapnik::image_32 & im, unsigned x, unsigned y, mapnik::color const& c) { im.setPixel(x, y, c.rgba()); -} +} boost::shared_ptr open_from_file(std::string const& filename) { diff --git a/bindings/python/mapnik_image_view.cpp b/bindings/python/mapnik_image_view.cpp index 9e07a29e6..f3cf2e44f 100644 --- a/bindings/python/mapnik_image_view.cpp +++ b/bindings/python/mapnik_image_view.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ extern "C" { diff --git a/bindings/python/mapnik_inmem_metawriter.cpp b/bindings/python/mapnik_inmem_metawriter.cpp index 44ebbdd08..34760f45b 100644 --- a/bindings/python/mapnik_inmem_metawriter.cpp +++ b/bindings/python/mapnik_inmem_metawriter.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_layer.cpp b/bindings/python/mapnik_layer.cpp index a37843b7f..0b2e8d63b 100644 --- a/bindings/python/mapnik_layer.cpp +++ b/bindings/python/mapnik_layer.cpp @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id: mapnik_layer.cc 17 2005-03-08 23:58:43Z pavlenko $ - // boost #include @@ -54,7 +52,7 @@ struct layer_pickle_suite : boost::python::pickle_suite { s.append(style_names[i]); } - return boost::python::make_tuple(l.clear_label_cache(),l.getMinZoom(),l.getMaxZoom(),l.isQueryable(),l.datasource()->params(),l.cache_features(),s); + return boost::python::make_tuple(l.clear_label_cache(),l.min_zoom(),l.max_zoom(),l.queryable(),l.datasource()->params(),l.cache_features(),s); } static void @@ -72,11 +70,11 @@ struct layer_pickle_suite : boost::python::pickle_suite l.set_clear_label_cache(extract(state[0])); - l.setMinZoom(extract(state[1])); + l.set_min_zoom(extract(state[1])); - l.setMaxZoom(extract(state[2])); + l.set_max_zoom(extract(state[2])); - l.setQueryable(extract(state[3])); + l.set_queryable(extract(state[3])); mapnik::parameters params = extract(state[4]); l.set_datasource(datasource_cache::instance()->create(params)); @@ -128,7 +126,7 @@ void export_layer() "box2d(-1.0,-1.0,0.0,0.0) # default until a datasource is loaded\n" ) - .def("visible", &layer::isVisible, + .def("visible", &layer::visible, "Return True if this layer's data is active and visible at a given scale.\n" "\n" "Otherwise returns False.\n" @@ -149,8 +147,8 @@ void export_layer() ) .add_property("active", - &layer::isActive, - &layer::setActive, + &layer::active, + &layer::set_active, "Get/Set whether this layer is active and will be rendered.\n" "\n" "Usage:\n" @@ -199,8 +197,8 @@ void export_layer() ) .add_property("maxzoom", - &layer::getMaxZoom, - &layer::setMaxZoom, + &layer::max_zoom, + &layer::set_max_zoom, "Get/Set the maximum zoom lever of the layer.\n" "\n" "Usage:\n" @@ -214,8 +212,8 @@ void export_layer() ) .add_property("minzoom", - &layer::getMinZoom, - &layer::setMinZoom, + &layer::min_zoom, + &layer::set_min_zoom, "Get/Set the minimum zoom lever of the layer.\n" "\n" "Usage:\n" @@ -244,8 +242,8 @@ void export_layer() ) .add_property("queryable", - &layer::isQueryable, - &layer::setQueryable, + &layer::queryable, + &layer::set_queryable, "Get/Set whether this layer is queryable.\n" "\n" "Usage:\n" diff --git a/bindings/python/mapnik_line_pattern_symbolizer.cpp b/bindings/python/mapnik_line_pattern_symbolizer.cpp index aae24bac0..e982edf05 100644 --- a/bindings/python/mapnik_line_pattern_symbolizer.cpp +++ b/bindings/python/mapnik_line_pattern_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include diff --git a/bindings/python/mapnik_line_symbolizer.cpp b/bindings/python/mapnik_line_symbolizer.cpp index 062d52618..93f96e693 100644 --- a/bindings/python/mapnik_line_symbolizer.cpp +++ b/bindings/python/mapnik_line_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include "mapnik_enumeration.hpp" @@ -62,5 +61,9 @@ void export_line_symbolizer() (&line_symbolizer::get_stroke, return_value_policy()), &line_symbolizer::set_stroke) + .add_property("smooth", + &line_symbolizer::smooth, + &line_symbolizer::set_smooth, + "smooth value (0..1.0)") ; } diff --git a/bindings/python/mapnik_logger.cpp b/bindings/python/mapnik_logger.cpp new file mode 100644 index 000000000..b6c0aeba9 --- /dev/null +++ b/bindings/python/mapnik_logger.cpp @@ -0,0 +1,133 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include +#include + +using mapnik::logger::severity; +using mapnik::logger::format; +using mapnik::logger::output; + +void set_severity(const severity::type& s) +{ + severity::set(s); +} + +severity::type get_severity() +{ + return severity::get(); +} + +void set_object_severity(const std::string& object_name, const severity::type& s) +{ + severity::set_object(object_name, s); +} + +severity::type get_object_severity(const std::string& object_name) +{ + return severity::get_object(object_name); +} + + +void export_logger() +{ + using namespace boost::python; + + enum_("SeverityType") + .value("Info", severity::info) + .value("Debug", severity::debug) + .value("Warn", severity::warn) + .value("Error", severity::error) + .value("Fatal", severity::fatal) + .value("None", severity::none) + ; + +/* + using mapnik::singleton; + using mapnik::CreateStatic; + using namespace boost::python; + + class_,boost::noncopyable>("Singleton",no_init) + .def("instance",&singleton::instance, + return_value_policy()) + .staticmethod("instance") + ; + + class_ >, + boost::noncopyable>("Severity",no_init) + .def("get",&severity::get) + .def("set",&severity::set) + .def("get_object",&severity::get_object) + .def("set_object",&severity::set_object) + .staticmethod("get") + .staticmethod("set") + .staticmethod("get_object") + .staticmethod("set_object") + ; +*/ + + def("set_severity", &set_severity, + "\n" + "Set global logger severity.\n" + "\n" + "Usage:\n" + ">>> from mapnik import SeverityType, set_severity\n" + ">>> set_severity(SeverityType.None)\n" + ">>> set_severity(SeverityType.Info)\n" + ">>> set_severity(SeverityType.Debug)\n" + ">>> set_severity(SeverityType.Warn)\n" + ">>> set_severity(SeverityType.Error)\n" + ">>> set_severity(SeverityType.Fatal)\n" + ); + + def("get_severity", &get_severity, + "\n" + "Get global logger severity.\n" + "\n" + "Usage:\n" + ">>> from mapnik import get_severity\n" + ">>> get_severity()\n" + ); + + def("set_object_severity", &set_object_severity, + "\n" + "Set logger severity for a single object.\n" + "\n" + "Usage:\n" + ">>> from mapnik import SeverityType, set_object_severity\n" + ">>> set_object_severity('ogr', SeverityType.None)\n" + ">>> set_object_severity('gdal', SeverityType.Info)\n" + ">>> set_object_severity('cairo_renderer', SeverityType.Debug)\n" + ">>> set_object_severity('agg_renderer', SeverityType.Warn)\n" + ">>> set_object_severity('bindings', SeverityType.Error)\n" + ); + + def("get_object_severity", &get_object_severity, + "\n" + "Get logger severity for a single object.\n" + "\n" + "Usage:\n" + ">>> from mapnik import get_object_severity" + ">>> get_object_severity('ogr')\n" + ); + +} diff --git a/bindings/python/mapnik_map.cpp b/bindings/python/mapnik_map.cpp index ab89de292..3bc1ca983 100644 --- a/bindings/python/mapnik_map.cpp +++ b/bindings/python/mapnik_map.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id: mapnik_map.cc 17 2005-03-08 23:58:43Z pavlenko $ // boost #include @@ -62,7 +61,7 @@ struct map_pickle_suite : boost::python::pickle_suite Map::const_style_iterator end = m.styles().end(); for (; it != end; ++it) { - const std::string & name = it->first; + std::string const& name = it->first; const mapnik::feature_type_style & style = it->second; boost::python::tuple style_pair = boost::python::make_tuple(name,style); s.append(style_pair); @@ -117,10 +116,8 @@ struct map_pickle_suite : boost::python::pickle_suite std::vector& (Map::*layers_nonconst)() = &Map::layers; std::vector const& (Map::*layers_const)() const = &Map::layers; - -mapnik::parameters& (Map::*attr_nonconst)() = &Map::get_extra_attributes; mapnik::parameters& (Map::*params_nonconst)() = &Map::get_extra_parameters; - +boost::optional > const& (Map::*maximum_extent_const)() const = &Map::maximum_extent; mapnik::feature_type_style find_style(mapnik::Map const& m, std::string const& name) { @@ -153,7 +150,7 @@ bool has_metawriter(mapnik::Map const& m) // returns empty shared_ptr when the metawriter isn't found, or is // of the wrong type. empty pointers make it back to Python as a None. -mapnik::metawriter_inmem_ptr find_inmem_metawriter(const mapnik::Map &m, const std::string &name) { +mapnik::metawriter_inmem_ptr find_inmem_metawriter(const mapnik::Map & m, std::string const& name) { mapnik::metawriter_ptr metawriter = m.find_metawriter(name); mapnik::metawriter_inmem_ptr inmem; @@ -195,6 +192,18 @@ mapnik::Map map_deepcopy(mapnik::Map & m, boost::python::dict memo) return result; } +// TODO - find a simplier way to set optional to uninitialized +void set_maximum_extent(mapnik::Map & m, boost::optional > const& box) +{ + if (box) + { + m.set_maximum_extent(*box); + } + else + { + m.maximum_extent().reset(); + } +} void export_map() { @@ -482,7 +491,6 @@ void export_map() ) .def("__deepcopy__",&map_deepcopy) - .add_property("extra_attributes",make_function(attr_nonconst,return_value_policy()),"TODO") .add_property("parameters",make_function(params_nonconst,return_value_policy()),"TODO") .add_property("aspect_fix_mode", @@ -554,8 +562,8 @@ void export_map() ) .add_property("maximum_extent",make_function - (&Map::maximum_extent,return_value_policy()), - &Map::set_maximum_extent, + (maximum_extent_const,return_value_policy()), + &set_maximum_extent, "The maximum extent of the map.\n" "\n" "Usage:\n" diff --git a/bindings/python/mapnik_markers_symbolizer.cpp b/bindings/python/mapnik_markers_symbolizer.cpp index df0ae4606..d6388c6f7 100644 --- a/bindings/python/mapnik_markers_symbolizer.cpp +++ b/bindings/python/mapnik_markers_symbolizer.cpp @@ -19,9 +19,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include + #include #include #include @@ -60,7 +60,8 @@ struct markers_symbolizer_pickle_suite : boost::python::pickle_suite static boost::python::tuple getstate(markers_symbolizer const& p) { - return boost::python::make_tuple(p.get_allow_overlap());//,p.get_opacity()); + return boost::python::make_tuple(p.get_allow_overlap(), + p.get_ignore_placement());//,p.get_opacity()); } static void @@ -77,7 +78,8 @@ struct markers_symbolizer_pickle_suite : boost::python::pickle_suite } p.set_allow_overlap(extract(state[0])); - //p.set_opacity(extract(state[1])); + p.set_ignore_placement(extract(state[1])); + //p.set_opacity(extract(state[2])); } @@ -108,8 +110,19 @@ void export_markers_symbolizer() &markers_symbolizer::get_opacity, &markers_symbolizer::set_opacity, "Set/get the text opacity") + .add_property("ignore_placement", + &markers_symbolizer::get_ignore_placement, + &markers_symbolizer::set_ignore_placement) .add_property("transform", &mapnik::get_svg_transform, &mapnik::set_svg_transform) + .add_property("width", + &markers_symbolizer::get_width, + &markers_symbolizer::set_width, + "Set/get the marker width") + .add_property("height", + &markers_symbolizer::get_height, + &markers_symbolizer::set_height, + "Set/get the marker height") ; } diff --git a/bindings/python/mapnik_palette.cpp b/bindings/python/mapnik_palette.cpp index 4e6c39666..54b0b3146 100644 --- a/bindings/python/mapnik_palette.cpp +++ b/bindings/python/mapnik_palette.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_parameters.cpp b/bindings/python/mapnik_parameters.cpp index 35a06d312..15a2b47e5 100644 --- a/bindings/python/mapnik_parameters.cpp +++ b/bindings/python/mapnik_parameters.cpp @@ -25,6 +25,7 @@ #include // mapnik +#include #include #include #include @@ -102,7 +103,7 @@ struct parameters_pickle_suite : boost::python::pickle_suite } else { - std::clog << "could not unpickle key: " << key << "\n"; + MAPNIK_LOG_DEBUG(bindings) << "parameters_pickle_suite: Could not unpickle key=" << key; } } } diff --git a/bindings/python/mapnik_point_symbolizer.cpp b/bindings/python/mapnik_point_symbolizer.cpp index ddd10bf41..2ca6c9acb 100644 --- a/bindings/python/mapnik_point_symbolizer.cpp +++ b/bindings/python/mapnik_point_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include "mapnik_enumeration.hpp" diff --git a/bindings/python/mapnik_polygon_pattern_symbolizer.cpp b/bindings/python/mapnik_polygon_pattern_symbolizer.cpp index 6aee342b8..dc155c5f6 100644 --- a/bindings/python/mapnik_polygon_pattern_symbolizer.cpp +++ b/bindings/python/mapnik_polygon_pattern_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include diff --git a/bindings/python/mapnik_polygon_symbolizer.cpp b/bindings/python/mapnik_polygon_symbolizer.cpp index 4b4fb1b1a..06f35f0d8 100644 --- a/bindings/python/mapnik_polygon_symbolizer.cpp +++ b/bindings/python/mapnik_polygon_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include "mapnik_enumeration.hpp" @@ -84,7 +83,11 @@ void export_polygon_symbolizer() .add_property("gamma_method", &polygon_symbolizer::get_gamma_method, &polygon_symbolizer::set_gamma_method, - "Set/get the gamma correction method of the polygon") + "gamma correction method") + .add_property("smooth", + &polygon_symbolizer::smooth, + &polygon_symbolizer::set_smooth, + "smooth value (0..1.0)") ; } diff --git a/bindings/python/mapnik_proj_transform.cpp b/bindings/python/mapnik_proj_transform.cpp index ed5e7c9a0..7dec3b36b 100644 --- a/bindings/python/mapnik_proj_transform.cpp +++ b/bindings/python/mapnik_proj_transform.cpp @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // mapnik #include + // boost #include diff --git a/bindings/python/mapnik_projection.cpp b/bindings/python/mapnik_projection.cpp index f555ab11a..54fba845f 100644 --- a/bindings/python/mapnik_projection.cpp +++ b/bindings/python/mapnik_projection.cpp @@ -19,9 +19,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ -//boost +// boost #include // mapnik diff --git a/bindings/python/mapnik_python.cpp b/bindings/python/mapnik_python.cpp index 8d401b6f5..f78a836f7 100644 --- a/bindings/python/mapnik_python.cpp +++ b/bindings/python/mapnik_python.cpp @@ -67,6 +67,7 @@ void export_view_transform(); void export_raster_colorizer(); void export_inmem_metawriter(); void export_label_collision_detector(); +void export_logger(); #include #include @@ -289,6 +290,11 @@ unsigned mapnik_version() return MAPNIK_VERSION; } +std::string mapnik_version_string() +{ + return MAPNIK_VERSION_STRING; +} + // indicator for jpeg read/write support within libmapnik bool has_jpeg() { @@ -391,6 +397,7 @@ BOOST_PYTHON_MODULE(_mapnik) export_raster_colorizer(); export_inmem_metawriter(); export_label_collision_detector(); + export_logger(); def("render_grid",&render_grid, ( arg("map"), @@ -583,6 +590,7 @@ BOOST_PYTHON_MODULE(_mapnik) def("save_map_to_string", &save_map_to_string, save_map_to_string_overloads()); def("mapnik_version", &mapnik_version,"Get the Mapnik version number"); + def("mapnik_version_string", &mapnik_version_string,"Get the Mapnik version string"); def("has_jpeg", &has_jpeg, "Get jpeg read/write support status"); def("has_cairo", &has_cairo, "Get cairo library status"); def("has_pycairo", &has_pycairo, "Get pycairo module status"); diff --git a/bindings/python/mapnik_query.cpp b/bindings/python/mapnik_query.cpp index 08133b17a..f2b5c368f 100644 --- a/bindings/python/mapnik_query.cpp +++ b/bindings/python/mapnik_query.cpp @@ -19,11 +19,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include + +// mapnik #include #include + using mapnik::query; using mapnik::box2d; diff --git a/bindings/python/mapnik_raster_colorizer.cpp b/bindings/python/mapnik_raster_colorizer.cpp index 0aa43b3f2..7d9d6b755 100644 --- a/bindings/python/mapnik_raster_colorizer.cpp +++ b/bindings/python/mapnik_raster_colorizer.cpp @@ -19,10 +19,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include #include + +// mapnik #include using mapnik::raster_colorizer; diff --git a/bindings/python/mapnik_raster_symbolizer.cpp b/bindings/python/mapnik_raster_symbolizer.cpp index 63a18b851..dacaea5de 100644 --- a/bindings/python/mapnik_raster_symbolizer.cpp +++ b/bindings/python/mapnik_raster_symbolizer.cpp @@ -19,9 +19,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include + +// mapnik #include using mapnik::raster_symbolizer; diff --git a/bindings/python/mapnik_rule.cpp b/bindings/python/mapnik_rule.cpp index 528a87a63..378e22f10 100644 --- a/bindings/python/mapnik_rule.cpp +++ b/bindings/python/mapnik_rule.cpp @@ -19,13 +19,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include #include #include #include +// mapnik #include #include #include diff --git a/bindings/python/mapnik_shield_symbolizer.cpp b/bindings/python/mapnik_shield_symbolizer.cpp index 41eff7536..28ae7083e 100644 --- a/bindings/python/mapnik_shield_symbolizer.cpp +++ b/bindings/python/mapnik_shield_symbolizer.cpp @@ -20,9 +20,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include + +// mapnik #include #include #include diff --git a/bindings/python/mapnik_stroke.cpp b/bindings/python/mapnik_stroke.cpp index a75f614c6..1f21071c3 100644 --- a/bindings/python/mapnik_stroke.cpp +++ b/bindings/python/mapnik_stroke.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_style.cpp b/bindings/python/mapnik_style.cpp index 1ab130c04..9437e87d5 100644 --- a/bindings/python/mapnik_style.cpp +++ b/bindings/python/mapnik_style.cpp @@ -19,11 +19,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include #include +// mapnik #include "mapnik_enumeration.hpp" #include diff --git a/bindings/python/mapnik_symbolizer.cpp b/bindings/python/mapnik_symbolizer.cpp index a4c4c3512..bd87b0db8 100644 --- a/bindings/python/mapnik_symbolizer.cpp +++ b/bindings/python/mapnik_symbolizer.cpp @@ -19,10 +19,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include +// mapnik //symbolizer typdef here rather than mapnik/symbolizer.hpp #include diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp index 2a566d588..13de8478b 100644 --- a/bindings/python/mapnik_text_placement.cpp +++ b/bindings/python/mapnik_text_placement.cpp @@ -40,15 +40,15 @@ using namespace mapnik; /* Notes: -Overriding functions in inherited classes: -boost.python documentation doesn't really tell you how to do it. -But this helps: -http://www.gamedev.net/topic/446225-inheritance-in-boostpython/ + Overriding functions in inherited classes: + boost.python documentation doesn't really tell you how to do it. + But this helps: + http://www.gamedev.net/topic/446225-inheritance-in-boostpython/ -register_ptr_to_python is required for wrapped classes, but not for unwrapped. + register_ptr_to_python is required for wrapped classes, but not for unwrapped. -Functions don't have to be members of the class, but can also be -normal functions taking a ref to the class as first parameter. + Functions don't have to be members of the class, but can also be + normal functions taking a ref to the class as first parameter. */ namespace { @@ -251,8 +251,7 @@ struct ListNodeWrap: formatting::list_node, wrapper struct TextPlacementsWrap: text_placements, wrapper { - text_placement_info_ptr get_placement_info(double scale_factor_, dimension_type dim, - bool has_dimensions_) const + text_placement_info_ptr get_placement_info(double scale_factor_) const { python_block_auto_unblock b; return this->get_override("get_placement_info")(); @@ -262,8 +261,8 @@ struct TextPlacementsWrap: text_placements, wrapper struct TextPlacementInfoWrap: text_placement_info, wrapper { TextPlacementInfoWrap(text_placements const* parent, - double scale_factor_, dimension_type dim, bool has_dimensions_) - : text_placement_info(parent, scale_factor_, dim, has_dimensions_) + double scale_factor_) + : text_placement_info(parent, scale_factor_) { } @@ -330,6 +329,7 @@ void export_text_placement() .value("LEFT",J_LEFT) .value("MIDDLE",J_MIDDLE) .value("RIGHT",J_RIGHT) + .value("AUTO", J_AUTO) ; enumeration_("text_transform") @@ -340,7 +340,7 @@ void export_text_placement() ; class_("TextSymbolizer", - init<>()) + init<>()) .def(init()) .add_property("placements", &text_symbolizer::get_placement_options, @@ -358,7 +358,7 @@ void export_text_placement() class_with_converter - ("TextSymbolizerProperties") + ("TextSymbolizerProperties") .def_readwrite_convert("label_placement", &text_symbolizer_properties::label_placement) .def_readwrite_convert("horizontal_alignment", &text_symbolizer_properties::halign) .def_readwrite_convert("justify_alignment", &text_symbolizer_properties::jalign) @@ -382,15 +382,15 @@ void export_text_placement() .add_property ("format_tree", &text_symbolizer_properties::format_tree, &text_symbolizer_properties::set_format_tree); - /* from_xml, to_xml operate on mapnik's internal XML tree and don't make sense in python. - add_expressions isn't useful in python either. The result is only needed by - attribute_collector (which isn't exposed in python) and - it just calls add_expressions of the associated formatting tree. - set_old_style expression is just a compatibility wrapper and doesn't need to be exposed in python. */ - ; + /* from_xml, to_xml operate on mapnik's internal XML tree and don't make sense in python. + add_expressions isn't useful in python either. The result is only needed by + attribute_collector (which isn't exposed in python) and + it just calls add_expressions of the associated formatting tree. + set_old_style expression is just a compatibility wrapper and doesn't need to be exposed in python. */ + ; class_ - ("CharProperties") + ("CharProperties") .def(init()) //Copy constructor .def_readwrite("face_name", &char_properties::face_name) .def_readwrite("fontset", &char_properties::fontset) @@ -408,9 +408,9 @@ void export_text_placement() ; class_, - boost::noncopyable> - ("TextPlacements") + boost::shared_ptr, + boost::noncopyable> + ("TextPlacements") .def_readwrite("defaults", &text_placements::defaults) .def("get_placement_info", pure_virtual(&text_placements::get_placement_info)) /* TODO: add_expressions() */ @@ -418,49 +418,42 @@ void export_text_placement() register_ptr_to_python >(); class_, - boost::noncopyable> - ("TextPlacementInfo", - init()) + boost::shared_ptr, + boost::noncopyable> + ("TextPlacementInfo", + init()) .def("next", pure_virtual(&text_placement_info::next)) .def("get_actual_label_spacing", &text_placement_info::get_actual_label_spacing) .def("get_actual_minimum_distance", &text_placement_info::get_actual_minimum_distance) .def("get_actual_minimum_padding", &text_placement_info::get_actual_minimum_padding) .def_readwrite("properties", &text_placement_info::properties) .def_readwrite("scale_factor", &text_placement_info::scale_factor) - .def_readwrite("has_dimensions", &text_placement_info::has_dimensions) - .def_readwrite("dimensions", &text_placement_info::dimensions) - .def_readwrite("collect_extents", &text_placement_info::collect_extents) - .def_readwrite("extents", &text_placement_info::extents) - .def_readwrite("additional_boxes", &text_placement_info::additional_boxes) - .def_readwrite("envelopes", &text_placement_info::envelopes) -// .def_readwrite("placements", &text_placement_info::placements) ; register_ptr_to_python >(); class_, - boost::noncopyable> - ("ProcessedText", no_init) + boost::shared_ptr, + boost::noncopyable> + ("ProcessedText", no_init) .def("push_back", &processed_text::push_back) .def("clear", &processed_text::clear) ; class_, - boost::noncopyable> - ("ExpressionSet") + boost::shared_ptr, + boost::noncopyable> + ("ExpressionSet") .def("insert", &insert_expression); - ; + ; //TODO: Python namespace class_, - boost::noncopyable> - ("FormattingNode") + boost::shared_ptr, + boost::noncopyable> + ("FormattingNode") .def("apply", pure_virtual(&formatting::node::apply)) .def("add_expressions", &formatting::node::add_expressions, @@ -470,10 +463,10 @@ void export_text_placement() class_, - bases, - boost::noncopyable> - ("FormattingText", init()) + boost::shared_ptr, + bases, + boost::noncopyable> + ("FormattingText", init()) .def(init()) .def("apply", &formatting::text_node::apply, &TextNodeWrap::default_apply) .add_property("text", @@ -484,10 +477,10 @@ void export_text_placement() class_with_converter, - bases, - boost::noncopyable> - ("FormattingFormat") + boost::shared_ptr, + bases, + boost::noncopyable> + ("FormattingFormat") .def_readwrite_convert("text_size", &formatting::format_node::text_size) .def_readwrite_convert("face_name", &formatting::format_node::face_name) .def_readwrite_convert("character_spacing", &formatting::format_node::character_spacing) @@ -507,10 +500,10 @@ void export_text_placement() register_ptr_to_python >(); class_, - bases, - boost::noncopyable> - ("FormattingList", init<>()) + boost::shared_ptr, + bases, + boost::noncopyable> + ("FormattingList", init<>()) .def(init()) .def("append", &formatting::list_node::push_back) .def("apply", &formatting::list_node::apply, &ListNodeWrap::default_apply) @@ -518,15 +511,15 @@ void export_text_placement() .def("__getitem__", &ListNodeWrap::get_item) .def("__setitem__", &ListNodeWrap::set_item) .def("append", &ListNodeWrap::append) - ; + ; register_ptr_to_python >(); class_, - bases, - boost::noncopyable> - ("FormattingExpressionFormat") + boost::shared_ptr, + bases, + boost::noncopyable> + ("FormattingExpressionFormat") .def_readwrite("text_size", &formatting::expression_format::text_size) .def_readwrite("face_name", &formatting::expression_format::face_name) .def_readwrite("character_spacing", &formatting::expression_format::character_spacing) diff --git a/bindings/python/mapnik_threads.hpp b/bindings/python/mapnik_threads.hpp index b1ac3f4e6..85789ff61 100644 --- a/bindings/python/mapnik_threads.hpp +++ b/bindings/python/mapnik_threads.hpp @@ -29,8 +29,8 @@ namespace mapnik { class python_thread { /* Docs: - http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock - */ + http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock + */ public: static void unblock() { @@ -38,8 +38,8 @@ public: if (state.get()) { std::cerr << "ERROR: Python threads are already unblocked. " - "Unblocking again will loose the current state and " - "might crash later. Aborting!\n"; + "Unblocking again will loose the current state and " + "might crash later. Aborting!\n"; abort(); //This is a serious error and can't be handled in any other sane way } #endif @@ -59,9 +59,9 @@ public: if (thread_support && !state.get()) { std::cerr << "ERROR: Trying to restore python thread state, " - "but no state is saved. Can't continue and also " - "can't raise an exception because the python " - "interpreter might be non-function. Aborting!\n"; + "but no state is saved. Can't continue and also " + "can't raise an exception because the python " + "interpreter might be non-function. Aborting!\n"; abort(); } #endif diff --git a/bindings/python/mapnik_view_transform.cpp b/bindings/python/mapnik_view_transform.cpp index 7a9da32d5..090e65f9c 100644 --- a/bindings/python/mapnik_view_transform.cpp +++ b/bindings/python/mapnik_view_transform.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/python_cairo.cpp b/bindings/python/python_cairo.cpp index e5420c1b1..ee6c900c3 100644 --- a/bindings/python/python_cairo.cpp +++ b/bindings/python/python_cairo.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO) diff --git a/bindings/python/python_grid_utils.hpp b/bindings/python/python_grid_utils.hpp index 09b72573c..031adb46c 100644 --- a/bindings/python/python_grid_utils.hpp +++ b/bindings/python/python_grid_utils.hpp @@ -28,6 +28,7 @@ #include // mapnik +#include #include #include #include @@ -271,7 +272,7 @@ static void write_features(T const& grid_type, } else { - std::clog << "should not get here: key '" << key << "' not found in grid feature properties\n"; + MAPNIK_LOG_DEBUG(bindings) << "write_features: Should not get here: key " << key << " not found in grid feature properties"; } } } diff --git a/bindings/python/python_optional.hpp b/bindings/python/python_optional.hpp index da3279f2f..29c1990db 100644 --- a/bindings/python/python_optional.hpp +++ b/bindings/python/python_optional.hpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include @@ -102,8 +101,8 @@ struct python_optional : public boost::noncopyable /** This class works around a bug in boost python. - See http://osdir.com/ml/python.c++/2003-11/msg00158.html - */ + See http://osdir.com/ml/python.c++/2003-11/msg00158.html +*/ template class class_with_converter : public boost::python::class_ { @@ -131,8 +130,8 @@ public: self& def_readwrite_convert(char const* name, D const& d, char const* doc=0) { this->add_property(name, - boost::python::make_getter(d, boost::python::return_value_policy()), - boost::python::make_setter(d, boost::python::default_call_policies())); + boost::python::make_getter(d, boost::python::return_value_policy()), + boost::python::make_setter(d, boost::python::default_call_policies())); return *this; } }; diff --git a/demo/c++/Makefile b/demo/c++/Makefile index 09ba0378c..d30b71b40 100644 --- a/demo/c++/Makefile +++ b/demo/c++/Makefile @@ -1,5 +1,3 @@ -CXX = g++ - CXXFLAGS = $(shell mapnik-config --cflags) LDFLAGS = $(shell mapnik-config --libs --dep-libs --ldflags) diff --git a/demo/c++/build.py b/demo/c++/build.py index a9b87265c..9738347f9 100644 --- a/demo/c++/build.py +++ b/demo/c++/build.py @@ -47,7 +47,6 @@ rundemo = demo_env.Program('rundemo', source, LIBS=libraries, LINKFLAGS=env["CUS Depends(rundemo, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME'])) -# we don't install this app because the datasource paths are relative -# and we're not going to install the sample data. -#env.Install(install_prefix + '/bin', rundemo) -#env.Alias('install', install_prefix + '/bin') +# build locally if installing +if 'install' in COMMAND_LINE_TARGETS: + env.Alias('install',rundemo) diff --git a/demo/c++/rundemo.cpp b/demo/c++/rundemo.cpp index cb6c26c90..eb22729e9 100644 --- a/demo/c++/rundemo.cpp +++ b/demo/c++/rundemo.cpp @@ -70,7 +70,7 @@ int main ( int argc , char** argv) provpoly_style.add_rule(provpoly_rule_on); rule provpoly_rule_qc; - provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'")); + provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'")); provpoly_rule_qc.append(polygon_symbolizer(color(217, 235, 203))); provpoly_style.add_rule(provpoly_rule_qc); @@ -175,6 +175,7 @@ int main ( int argc , char** argv) parameters p; p["type"]="shape"; p["file"]="../data/boundaries"; + p["encoding"]="latin1"; layer lyr("Provinces"); lyr.set_datasource(datasource_cache::instance()->create(p)); diff --git a/demo/python/rundemo.py b/demo/python/rundemo.py index 0fda7526d..bd9639a4b 100644 --- a/demo/python/rundemo.py +++ b/demo/python/rundemo.py @@ -138,7 +138,9 @@ qcdrain_lyr.datasource = mapnik.Shapefile(file='../data/qcdrainage') qcdrain_style = mapnik.Style() qcdrain_rule = mapnik.Rule() qcdrain_rule.filter = mapnik.Expression('[HYC] = 8') -qcdrain_rule.symbols.append(mapnik.PolygonSymbolizer(mapnik.Color(153, 204, 255))) +sym = mapnik.PolygonSymbolizer(mapnik.Color(153, 204, 255)) +sym.smooth = 1.0 # very smooth +qcdrain_rule.symbols.append(sym) qcdrain_style.rules.append(qcdrain_rule) m.append_style('drainage', qcdrain_style) diff --git a/demo/viewer/layerlistmodel.cpp b/demo/viewer/layerlistmodel.cpp index b6dae0d20..68280dce1 100644 --- a/demo/viewer/layerlistmodel.cpp +++ b/demo/viewer/layerlistmodel.cpp @@ -49,7 +49,7 @@ QVariant LayerListModel::data(QModelIndex const& index,int role) const else if (role == Qt::DecorationRole) { double scale = map_->scale(); - if (map_->layers().at(index.row()).isVisible(scale)) + if (map_->layers().at(index.row()).visible(scale)) { return QIcon(":/images/globe.png"); } @@ -60,7 +60,7 @@ QVariant LayerListModel::data(QModelIndex const& index,int role) const } else if (role == Qt::CheckStateRole) { - if (map_->layers().at(index.row()).isActive()) + if (map_->layers().at(index.row()).active()) return QVariant(Qt::Checked); else return QVariant(Qt::Unchecked); @@ -92,7 +92,7 @@ bool LayerListModel::setData(const QModelIndex &index, { int status = value.toInt(); std::vector & layers = const_cast& >(map_->layers()); - layers.at(index.row()).setActive(status); + layers.at(index.row()).set_active(status); emit dataChanged(index, index); return true; } diff --git a/demo/viewer/mapwidget.cpp b/demo/viewer/mapwidget.cpp index f9a29ee45..103b4d9cd 100644 --- a/demo/viewer/mapwidget.cpp +++ b/demo/viewer/mapwidget.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "mapwidget.hpp" #include "info_dialog.hpp" @@ -157,7 +158,7 @@ void MapWidget::mousePressEvent(QMouseEvent* e) if (int(index) != selectedLayer_) continue; layer & layer = map_->layers()[index]; - if (!layer.isVisible(scale_denom)) continue; + if (!layer.visible(scale_denom)) continue; std::string name = layer.name(); double x = e->x(); double y = e->y(); @@ -487,7 +488,7 @@ void MapWidget::updateMap() } catch (mapnik::config_error & ex) { - std::cerr << ex.what() << std::endl; + std::cerr << ex.what() << std::endl; } catch (...) { diff --git a/docs/contributing.markdown b/docs/contributing.markdown index b3fba320a..6bc272f18 100644 --- a/docs/contributing.markdown +++ b/docs/contributing.markdown @@ -95,6 +95,18 @@ If you see bits of code around that do not follow these please don't hesitate to (int)value; // no +#### Use const keyword after the type + + std::string const& variable_name // preferred, for consistency + + const std::string & variable_name // no + +#### Pass built-in types by value, all others by const& + + void my_function(int double val); // if int, char, double, etc pass by value + + void my_function(std::string const& val); // if std::string or user type, pass by const& + #### Shared pointers should be created with [boost::make_shared](http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/make_shared.html) where possible #### Function definitions should not be separated from their arguments: diff --git a/include/mapnik/agg_helpers.hpp b/include/mapnik/agg_helpers.hpp new file mode 100644 index 000000000..e605194fe --- /dev/null +++ b/include/mapnik/agg_helpers.hpp @@ -0,0 +1,91 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_AGG_HELPERS_HPP +#define MAPNIK_AGG_HELPERS_HPP + +#include "agg_gamma_functions.h" +#include "agg_math_stroke.h" + +namespace mapnik { + +template +void set_gamma_method(T0 const& obj, T1 & ras_ptr) +{ + switch (obj.get_gamma_method()) + { + case GAMMA_POWER: + ras_ptr->gamma(agg::gamma_power(obj.get_gamma())); + break; + case GAMMA_LINEAR: + ras_ptr->gamma(agg::gamma_linear(0.0, obj.get_gamma())); + break; + case GAMMA_NONE: + ras_ptr->gamma(agg::gamma_none()); + break; + case GAMMA_THRESHOLD: + ras_ptr->gamma(agg::gamma_threshold(obj.get_gamma())); + break; + case GAMMA_MULTIPLY: + ras_ptr->gamma(agg::gamma_multiply(obj.get_gamma())); + break; + default: + ras_ptr->gamma(agg::gamma_power(obj.get_gamma())); + } +} + +template +void set_join_caps(Stroke const& stroke_, PathType & stroke) +{ + line_join_e join=stroke_.get_line_join(); + switch (join) + { + case MITER_JOIN: + stroke.generator().line_join(agg::miter_join); + break; + case MITER_REVERT_JOIN: + stroke.generator().line_join(agg::miter_join); + break; + case ROUND_JOIN: + stroke.generator().line_join(agg::round_join); + break; + default: + stroke.generator().line_join(agg::bevel_join); + } + + line_cap_e cap=stroke_.get_line_cap(); + switch (cap) + { + case BUTT_CAP: + stroke.generator().line_cap(agg::butt_cap); + break; + case SQUARE_CAP: + stroke.generator().line_cap(agg::square_cap); + break; + default: + stroke.generator().line_cap(agg::round_cap); + } +} + +} + +#endif //MAPNIK_AGG_HELPERS_HPP diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index 4522e3aeb..d7e09049a 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -29,10 +29,6 @@ #include #include #include -//#include - -// agg -//#include "agg_trans_affine.h" // boost #include @@ -67,10 +63,10 @@ public: ~agg_renderer(); void start_map_processing(Map const& map); void end_map_processing(Map const& map); - void start_layer_processing(layer const& lay); + void start_layer_processing(layer const& lay, box2d const& query_extent); void end_layer_processing(layer const& lay); void render_marker(pixel_position const& pos, marker const& marker, agg::trans_affine const& tr, double opacity); - + void process(point_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans); @@ -123,7 +119,7 @@ private: face_manager font_manager_; boost::shared_ptr detector_; boost::scoped_ptr ras_ptr; - + box2d query_extent_; void setup(Map const &m); }; } diff --git a/include/mapnik/boolean.hpp b/include/mapnik/boolean.hpp new file mode 100644 index 000000000..bc9b46cc4 --- /dev/null +++ b/include/mapnik/boolean.hpp @@ -0,0 +1,99 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ +#ifndef MAPNIK_BOOLEAN_HPP +#define MAPNIK_BOOLEAN_HPP + +// std +#include + +// boost +#include + +namespace mapnik +{ +/** Helper for class bool */ +class boolean { +public: + boolean(): b_(false) {} + boolean(bool b) : b_(b) {} + boolean(boolean const& b) : b_(b.b_) {} + + operator bool() const + { + return b_; + } + + boolean & operator = (boolean const& other) + { + b_ = other.b_; + return * this; + } + + boolean & operator = (bool other) + { + b_ = other; + return * this; + } + +private: + bool b_; +}; + +/** Special stream input operator for boolean values */ +template +std::basic_istream & +operator >> ( std::basic_istream & s, boolean & b ) +{ + std::string word; + s >> word; + boost::algorithm::to_lower(word); + if ( s ) + { + if ( word == "true" || word == "yes" || word == "on" || + word == "1") + { + b = true; + } + else if ( word == "false" || word == "no" || word == "off" || + word == "0") + { + b = false; + } + else + { + s.setstate( std::ios::failbit ); + } + } + return s; +} + +template +std::basic_ostream & +operator << ( std::basic_ostream & s, boolean const& b ) +{ + s << ( b ? "true" : "false" ); + return s; +} + +} + +#endif // MAPNIK_BOOLEAN_HPP diff --git a/include/mapnik/cairo_renderer.hpp b/include/mapnik/cairo_renderer.hpp index 1c11e605c..408662ef9 100644 --- a/include/mapnik/cairo_renderer.hpp +++ b/include/mapnik/cairo_renderer.hpp @@ -78,7 +78,7 @@ protected: public: ~cairo_renderer_base(); void start_map_processing(Map const& map); - void start_layer_processing(layer const& lay); + void start_layer_processing(layer const& lay, box2d const& query_extent); void end_layer_processing(layer const& lay); void process(point_symbolizer const& sym, mapnik::feature_ptr const& feature, @@ -123,7 +123,7 @@ public: } protected: - void render_marker(pixel_position const& pos, marker const& marker, const agg::trans_affine & mtx, double opacity=1.0); + void render_marker(pixel_position const& pos, marker const& marker, const agg::trans_affine & mtx, double opacity=1.0, bool recenter=true); Map const& m_; Cairo::RefPtr context_; @@ -132,6 +132,7 @@ protected: face_manager font_manager_; cairo_face_manager face_manager_; label_collision_detector4 detector_; + box2d query_extent_; }; template diff --git a/include/mapnik/char_info.hpp b/include/mapnik/char_info.hpp index a1417735f..12da2bf31 100644 --- a/include/mapnik/char_info.hpp +++ b/include/mapnik/char_info.hpp @@ -31,11 +31,24 @@ struct char_properties; class char_info { public: char_info(unsigned c_, double width_, double ymax_, double ymin_, double line_height_) - : c(c_), width(width_), line_height(line_height_), ymin(ymin_), ymax(ymax_) + : c(c_), + width(width_), + line_height(line_height_), + ymin(ymin_), + ymax(ymax_), + avg_height(ymax_-ymin_), + format() { } + char_info() - : c(0), width(0), line_height(0), ymin(0), ymax(0) + : c(0), + width(0), + line_height(0), + ymin(0), + ymax(0), + avg_height(0), + format() { } diff --git a/include/mapnik/color.hpp b/include/mapnik/color.hpp index c7f2de610..ad9806276 100644 --- a/include/mapnik/color.hpp +++ b/include/mapnik/color.hpp @@ -137,6 +137,14 @@ public: std::string to_hex_string() const; }; +template +std::basic_ostream & +operator << ( std::basic_ostream & s, mapnik::color const& c ) +{ + std::string hex_string( c.to_string() ); + s << hex_string; + return s; +} } diff --git a/include/mapnik/color_factory.hpp b/include/mapnik/color_factory.hpp index 3d92cb193..418c244a0 100644 --- a/include/mapnik/color_factory.hpp +++ b/include/mapnik/color_factory.hpp @@ -25,134 +25,26 @@ // mapnik #include -#include -#include // boost #include -#include - -// boost 1.41 -> 1.44 compatibility, to be removed in mapnik 2.1 (dane) -#if BOOST_VERSION >= 104500 -#include namespace mapnik { +class color; + +template struct css_color_grammar; class MAPNIK_DECL color_factory : boost::noncopyable { public: - static void init_from_string(color & c, std::string const& css_color) - { - typedef std::string::const_iterator iterator_type; - typedef mapnik::css_color_grammar css_color_grammar; - - css_color_grammar g; - iterator_type first = css_color.begin(); - iterator_type last = css_color.end(); - bool result = - boost::spirit::qi::phrase_parse(first, - last, - g, - boost::spirit::ascii::space, - c); - if (!result) - { - throw config_error(std::string("Failed to parse color value: ") + - "Expected a CSS color, but got '" + css_color + "'"); - } - } + static void init_from_string(color & c, std::string const& css_color); static bool parse_from_string(color & c, std::string const& css_color, - mapnik::css_color_grammar const& g) - { - std::string::const_iterator first = css_color.begin(); - std::string::const_iterator last = css_color.end(); - bool result = - boost::spirit::qi::phrase_parse(first, - last, - g, - boost::spirit::ascii::space, - c); - return result && (first == last); - } + mapnik::css_color_grammar const& g); - static color from_string(std::string const& css_color) - { - color c; - init_from_string(c,css_color); - return c; - } + static color from_string(std::string const& css_color); }; } -#else -#include - -namespace mapnik { - -class MAPNIK_DECL color_factory : boost::noncopyable -{ -public: - - static bool parse_from_string(color & c, std::string const& css_color, - mapnik::css_color_grammar const& g) - { - std::string::const_iterator first = css_color.begin(); - std::string::const_iterator last = css_color.end(); - mapnik::css css_; - bool result = - boost::spirit::qi::phrase_parse(first, - last, - g, - boost::spirit::ascii::space, - css_); - if (result && (first == last)) - { - c.set_red(css_.r); - c.set_green(css_.g); - c.set_blue(css_.b); - c.set_alpha(css_.a); - return true; - } - return false; - } - - static void init_from_string(color & c, std::string const& css_color) - { - typedef std::string::const_iterator iterator_type; - typedef mapnik::css_color_grammar css_color_grammar; - - css_color_grammar g; - iterator_type first = css_color.begin(); - iterator_type last = css_color.end(); - mapnik::css css_; - bool result = - boost::spirit::qi::phrase_parse(first, - last, - g, - boost::spirit::ascii::space, - css_); - if (!result) - { - throw config_error(std::string("Failed to parse color value: ") + - "Expected a CSS color, but got '" + css_color + "'"); - } - c.set_red(css_.r); - c.set_green(css_.g); - c.set_blue(css_.b); - c.set_alpha(css_.a); - } - - static color from_string(std::string const& css_color) - { - color c; - init_from_string(c,css_color); - return c; - } -}; -} - -#endif - #endif // MAPNIK_COLOR_FACTORY_HPP diff --git a/include/mapnik/config.hpp b/include/mapnik/config.hpp index d25d74f62..88399b19c 100644 --- a/include/mapnik/config.hpp +++ b/include/mapnik/config.hpp @@ -25,8 +25,6 @@ // Windows DLL support -#define MAPNIK_SUPPORTS_GRID_RENDERER - #ifdef _WINDOWS # define MAPNIK_EXP __declspec (dllexport) # define MAPNIK_IMP __declspec (dllimport) diff --git a/include/mapnik/config_error.hpp b/include/mapnik/config_error.hpp index b25ae07f1..a889bc39e 100644 --- a/include/mapnik/config_error.hpp +++ b/include/mapnik/config_error.hpp @@ -28,30 +28,28 @@ namespace mapnik { +class xml_node; class config_error : public std::exception { public: - config_error() {} - - config_error( const std::string & what ) : - what_( what ) - { - } + config_error(std::string const& what); + config_error(std::string const& what, xml_node const& node); + config_error(std::string const& what, unsigned line_number, std::string const& filename); virtual ~config_error() throw() {} - virtual const char * what() const throw() - { - return what_.c_str(); - } - - void append_context(const std::string & ctx) const - { - what_ += " " + ctx; - } + virtual const char * what() const throw(); + void append_context(const std::string & ctx) const; + void append_context(const std::string & ctx, xml_node const& node) const; + void append_context(xml_node const& node) const; protected: mutable std::string what_; + mutable unsigned line_number_; + mutable std::string file_; + mutable std::string node_name_; + mutable std::string msg_; }; + } #endif // MAPNIK_CONFIG_ERROR_HPP diff --git a/include/mapnik/ctrans.hpp b/include/mapnik/ctrans.hpp index 6d350c540..2456f943d 100644 --- a/include/mapnik/ctrans.hpp +++ b/include/mapnik/ctrans.hpp @@ -24,6 +24,7 @@ #define MAPNIK_CTRANS_HPP // mapnik +#include #include #include #include @@ -72,16 +73,16 @@ template struct MAPNIK_DECL coord_transform2 { typedef std::size_t size_type; - typedef typename Geometry::value_type value_type; + //typedef typename Geometry::value_type value_type; coord_transform2(Transform const& t, - Geometry const& geom, + Geometry & geom, proj_transform const& prj_trans) : t_(t), geom_(geom), prj_trans_(prj_trans) {} - unsigned vertex(double *x, double *y) const + unsigned vertex(double *x, double *y) { unsigned command = SEG_MOVETO; bool ok = false; @@ -115,7 +116,7 @@ struct MAPNIK_DECL coord_transform2 private: Transform const& t_; - Geometry const& geom_; + Geometry & geom_; proj_transform const& prj_trans_; }; @@ -239,10 +240,10 @@ struct MAPNIK_DECL coord_transform_parallel angle_a = atan2((m_pre_y-m_cur_y),(m_pre_x-m_cur_x)); dx_pre = cos(angle_a + pi_by_2); dy_pre = sin(angle_a + pi_by_2); -#ifdef MAPNIK_DEBUG - std::clog << "offsetting line by: " << offset_ << "\n"; - std::clog << "initial dx=" << (dx_pre * offset_) << " dy=" << (dy_pre * offset_) << "\n"; -#endif + + MAPNIK_LOG_DEBUG(ctrans) << "coord_transform_parallel: Offsetting line by=" << offset_; + MAPNIK_LOG_DEBUG(ctrans) << "coord_transform_parallel: Initial dx=" << (dx_pre * offset_) << ",dy=" << (dy_pre * offset_); + *x = m_pre_x + (dx_pre * offset_); *y = m_pre_y + (dy_pre * offset_); m_status = process; @@ -289,15 +290,14 @@ struct MAPNIK_DECL coord_transform_parallel } else // skip sharp spikes { - -#ifdef MAPNIK_DEBUG +#ifdef MAPNIK_LOG dx_curr = cos(angle_a + pi_by_2); dy_curr = sin(angle_a + pi_by_2); sin_curve = dx_curr*dy_pre-dy_curr*dx_pre; - std::clog << "angle a: " << angle_a << "\n"; - std::clog << "angle b: " << angle_b << "\n"; - std::clog << "h: " << h << "\n"; - std::clog << "sin_curve: " << sin_curve << "\n"; + MAPNIK_LOG_DEBUG(ctrans) << "coord_transform_parallel: angle a=" << angle_a; + MAPNIK_LOG_DEBUG(ctrans) << "coord_transform_parallel: angle b=" << angle_b; + MAPNIK_LOG_DEBUG(ctrans) << "coord_transform_parallel: h=" << h; + MAPNIK_LOG_DEBUG(ctrans) << "coord_transform_parallel: sin_curve=" << sin_curve; #endif m_status = process; break; @@ -309,21 +309,19 @@ struct MAPNIK_DECL coord_transform_parallel sin_curve = dx_curr*dy_pre-dy_curr*dx_pre; cos_curve = -dx_pre*dx_curr-dy_pre*dy_curr; - #ifdef MAPNIK_DEBUG - std::clog << "sin_curve value: " << sin_curve << "\n"; - #endif + MAPNIK_LOG_DEBUG(ctrans) << "coord_transform_parallel: sin_curve value=" << sin_curve; if(sin_curve > -0.3 && sin_curve < 0.3) { - angle_b = atan2((m_cur_y-m_next_y),(m_cur_x-m_next_x)); - h = tan((angle_b - angle_a)/2.0); - *x = m_cur_x + (dx_curr * offset_) - h * (dy_curr * offset_); - *y = m_cur_y + (dy_curr * offset_) + h * (dx_curr * offset_); + angle_b = atan2((m_cur_y-m_next_y),(m_cur_x-m_next_x)); + h = tan((angle_b - angle_a)/2.0); + *x = m_cur_x + (dx_curr * offset_) - h * (dy_curr * offset_); + *y = m_cur_y + (dy_curr * offset_) + h * (dx_curr * offset_); } else { - if (angle_b - angle_a > 0) - h = -1.0*(1.0+cos_curve)/sin_curve; - else - h = (1.0+cos_curve)/sin_curve; - *x = m_cur_x + (dx_curr + base_shift*dy_curr)*offset_; - *y = m_cur_y + (dy_curr - base_shift*dx_curr)*offset_; + if (angle_b - angle_a > 0) + h = -1.0*(1.0+cos_curve)/sin_curve; + else + h = (1.0+cos_curve)/sin_curve; + *x = m_cur_x + (dx_curr + base_shift*dy_curr)*offset_; + *y = m_cur_y + (dy_curr - base_shift*dx_curr)*offset_; } */ @@ -380,20 +378,27 @@ class CoordTransform private: int width_; int height_; - double sx_; - double sy_; box2d extent_; double offset_x_; double offset_y_; + double sx_; + double sy_; public: CoordTransform(int width, int height, const box2d& extent, double offset_x = 0, double offset_y = 0) - : width_(width), height_(height), extent_(extent), - offset_x_(offset_x), offset_y_(offset_y) + : width_(width), + height_(height), + extent_(extent), + offset_x_(offset_x), + offset_y_(offset_y), + sx_(1.0), + sy_(1.0) { - sx_ = static_cast(width_) / extent_.width(); - sy_ = static_cast(height_) / extent_.height(); + if (extent_.width() > 0) + sx_ = static_cast(width_) / extent_.width(); + if (extent_.height() > 0) + sy_ = static_cast(height_) / extent_.height(); } inline int width() const diff --git a/include/mapnik/datasource.hpp b/include/mapnik/datasource.hpp index 5cfd1bde5..6ae828a94 100644 --- a/include/mapnik/datasource.hpp +++ b/include/mapnik/datasource.hpp @@ -45,25 +45,30 @@ typedef MAPNIK_DECL boost::shared_ptr feature_ptr; struct MAPNIK_DECL Featureset : private boost::noncopyable { - virtual feature_ptr next()=0; - virtual ~Featureset() {}; + virtual feature_ptr next() = 0; + virtual ~Featureset() {} }; typedef MAPNIK_DECL boost::shared_ptr featureset_ptr; class MAPNIK_DECL datasource_exception : public std::exception { -private: - std::string message_; public: - datasource_exception(const std::string& message=std::string("no reason")) - :message_(message) {} + datasource_exception(const std::string& message = std::string("no reason")) + : message_(message) + { + } + + ~datasource_exception() throw() + { + } - ~datasource_exception() throw() {} virtual const char* what() const throw() { return message_.c_str(); } +private: + std::string message_; }; class MAPNIK_DECL datasource : private boost::noncopyable @@ -82,9 +87,10 @@ public: }; datasource (parameters const& params) - : params_(params), + : params_(params), is_bound_(false) - {} + { + } /*! * @brief Get the configuration parameters of the data source. @@ -102,19 +108,19 @@ public: * @brief Get the type of the datasource * @return The type of the datasource (Vector or Raster) */ - virtual datasource_t type() const=0; + virtual datasource_t type() const = 0; /*! * @brief Connect to the datasource */ - virtual void bind() const {}; + virtual void bind() const {} - virtual featureset_ptr features(const query& q) const=0; - virtual featureset_ptr features_at_point(coord2d const& pt) const=0; - virtual box2d envelope() const=0; - virtual boost::optional get_geometry_type() const=0; - virtual layer_descriptor get_descriptor() const=0; - virtual ~datasource() {}; + virtual featureset_ptr features(const query& q) const = 0; + virtual featureset_ptr features_at_point(coord2d const& pt) const = 0; + virtual box2d envelope() const = 0; + virtual boost::optional get_geometry_type() const = 0; + virtual layer_descriptor get_descriptor() const = 0; + virtual ~datasource() {} protected: parameters params_; mutable bool is_bound_; @@ -124,7 +130,6 @@ typedef std::string datasource_name(); typedef datasource* create_ds(const parameters& params, bool bind); typedef void destroy_ds(datasource *ds); - class datasource_deleter { public: @@ -136,7 +141,6 @@ public: typedef boost::shared_ptr datasource_ptr; - #define DATASOURCE_PLUGIN(classname) \ extern "C" MAPNIK_EXP std::string datasource_name() \ { \ @@ -149,8 +153,7 @@ typedef boost::shared_ptr datasource_ptr; extern "C" MAPNIK_EXP void destroy(datasource *ds) \ { \ delete ds; \ - } \ - // + } } diff --git a/include/mapnik/debug.hpp b/include/mapnik/debug.hpp new file mode 100644 index 000000000..93ff737d0 --- /dev/null +++ b/include/mapnik/debug.hpp @@ -0,0 +1,279 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_DEBUG_HPP +#define MAPNIK_DEBUG_HPP + +// mapnik (should not depend on anything that need to use this) +#include +#include + +// boost +#include +#include +#ifdef MAPNIK_THREADSAFE +#include +#endif + +// std +#include +#include +#include +#include +#include + + +namespace mapnik { + namespace logger { + + class MAPNIK_DECL severity : + public singleton, + private boost::noncopyable + { + public: + enum type + { + info, + debug, + warn, + error, + fatal, + none + }; + + typedef boost::unordered_map severity_map; + + // globally get security level + static type get() + { + return severity_level_; + } + + // globally set security level + static void set(const type& severity_level) + { +#ifdef MAPNIK_THREADSAFE + boost::mutex::scoped_lock lock(mutex_); +#endif + + severity_level_ = severity_level; + } + + // per object get security level + static type get_object(const std::string& object_name) + { + severity_map::iterator it = object_severity_level_.find(object_name); + if (object_name.empty() || it == object_severity_level_.end()) + { + return severity_level_; + } + else + { + return it->second; + } + } + + // per object set security level + static void set_object(const std::string& object_name, + const type& security_level) + { +#ifdef MAPNIK_THREADSAFE + boost::mutex::scoped_lock lock(mutex_); +#endif + if (! object_name.empty()) + { + object_severity_level_[object_name] = security_level; + } + } + + private: + static type severity_level_; + static severity_map object_severity_level_; + +#ifdef MAPNIK_THREADSAFE + static boost::mutex mutex_; +#endif + }; + + + class MAPNIK_DECL format : + public singleton, + private boost::noncopyable + { + public: + + static std::string get() + { + return format_; + } + + static void set(const std::string& format) + { +#ifdef MAPNIK_THREADSAFE + boost::mutex::scoped_lock lock(mutex_); +#endif + format_ = format; + } + + static std::string str(); + + private: + static std::string format_; + +#ifdef MAPNIK_THREADSAFE + static boost::mutex mutex_; +#endif + }; + + + class MAPNIK_DECL output : + public singleton, + private boost::noncopyable + { + public: + static void use_file(const std::string& filepath); + static void use_console(); + + private: + static std::ofstream file_output_; + static std::string file_name_; + static std::streambuf* saved_buf_; + }; + + + template + class clog_sink + { + public: + typedef std::basic_ostringstream stream_buffer; + + void operator()(const stream_buffer &s) + { +#ifdef MAPNIK_THREADSAFE + static boost::mutex mutex; + boost::mutex::scoped_lock lock(mutex); +#endif + std::clog << format::str() << " " << s.str() << std::endl; + } + }; + + + template