<commit_before>var tilelive = require('tilelive');
var step = require('step');
var _ = require('underscore');
var assert = require('assert');

var RendererParams = require('../renderer_params');

require('tilelive-mapnik').registerProtocols(tilelive);

var COLUMN_TYPE_GEOMETRY = 'geometry';
var COLUMN_TYPE_RASTER = 'raster';

var COLUMN_NAME_DEFAULT = global.environment.postgres.geometry_field || 'the_geom_webmercator';
var COLUMN_TYPE_DEFAULT = COLUMN_TYPE_GEOMETRY;

var MAPNIK_COLUMN_NAME = '__cdb_the_geom';

var DEFAULT_TILE_SIZE = 256;

function MapnikFactory(mmlStore, options) {
    this._mmlStore = mmlStore;
    this._options = options;

    var tile_scale_factors = options.scale_factors || [1, 2];

    this.tile_scale_factors = tile_scale_factors.reduce(function(previousValue, currentValue) {
        previousValue[currentValue] = DEFAULT_TILE_SIZE * currentValue;
        return previousValue;
    }, {});

    // Set default mapnik options
    this._mapnik_opts = _.defaults(options.mapnik_opts || {}, {

        // Metatile is the number of tiles-per-side that are going
        // to be rendered at once. If all of them will be requested
        // we'd have saved time. If only one will be used, we'd have
        // wasted time.
        //
        // Defaults to 2 as of tilelive-mapnik@0.3.2
        //
        // We'll assume an average of a 4x4 viewport
        metatile: 4,

        // Buffer size is the tickness in pixel of a buffer
        // around the rendered (meta?)tile.
        //
        // This is important for labels and other marker that overlap tile boundaries.
        // Setting to 128 ensures no render artifacts.
        // 64 may have artifacts but is faster.
        // Less important if we can turn metatiling on.
        //
        // defaults to 128 as of tilelive-mapnik@0.3.2
        //
        bufferSize: 64
    });
}

module.exports = MapnikFactory;


MapnikFactory.prototype.getRenderer = function(mapConfig, params, format, layer, callback) {
    var self = this;
    var mml_builder;

    params = _.defaults(params, this.mapConfigToMMLBuilderConfig(mapConfig));

    var scaleFactor = _.isUndefined(params.scale_factor) ? 1 : +params.scale_factor,
        tileSize = this.tile_scale_factors[scaleFactor];

    if (!tileSize) {
        var err = new Error('Tile with specified resolution not found');
        err.http_status = 404;
        return callback(err);
    }

    step(
        function initBuilder() {
            // create an mapnik mml builder object
            mml_builder = self._mmlStore.mml_builder(params, this);
        },
        function generateXML(err) {
            assert.ifError(err);
            mml_builder.toXML(this);
        },
        function loadMapnik(err, xml) {
            assert.ifError(err);

            var query = {
                // TODO: document what `base` is
                base: RendererParams.createKey(params) + '/xia',
                metatile: self._mapnik_opts.metatile,
                bufferSize: self._mapnik_opts.bufferSize,
                poolSize: self._mapnik_opts.poolSize,
                scale: scaleFactor,
                tileSize: tileSize,
                autoLoadFonts: false,
                internal_cache: false
            };

            // build full document to pass to tilelive
            var uri = {
                query: query,
                protocol: 'mapnik:',
                xml: xml,
                strict: !!params.strict // force boolean
            };

            // hand off to tilelive to create a renderer<commit_msg>Remove base uri option as it has no effect when using xml as string<commit_after>var tilelive = require('tilelive');
var step = require('step');
var _ = require('underscore');
var assert = require('assert');

require('tilelive-mapnik').registerProtocols(tilelive);

var COLUMN_TYPE_GEOMETRY = 'geometry';
var COLUMN_TYPE_RASTER = 'raster';

var COLUMN_NAME_DEFAULT = global.environment.postgres.geometry_field || 'the_geom_webmercator';
var COLUMN_TYPE_DEFAULT = COLUMN_TYPE_GEOMETRY;

var MAPNIK_COLUMN_NAME = '__cdb_the_geom';

var DEFAULT_TILE_SIZE = 256;

function MapnikFactory(mmlStore, options) {
    this._mmlStore = mmlStore;
    this._options = options;

    var tile_scale_factors = options.scale_factors || [1, 2];

    this.tile_scale_factors = tile_scale_factors.reduce(function(previousValue, currentValue) {
        previousValue[currentValue] = DEFAULT_TILE_SIZE * currentValue;
        return previousValue;
    }, {});

    // Set default mapnik options
    this._mapnik_opts = _.defaults(options.mapnik_opts || {}, {

        // Metatile is the number of tiles-per-side that are going
        // to be rendered at once. If all of them will be requested
        // we'd have saved time. If only one will be used, we'd have
        // wasted time.
        //
        // Defaults to 2 as of tilelive-mapnik@0.3.2
        //
        // We'll assume an average of a 4x4 viewport
        metatile: 4,

        // Buffer size is the tickness in pixel of a buffer
        // around the rendered (meta?)tile.
        //
        // This is important for labels and other marker that overlap tile boundaries.
        // Setting to 128 ensures no render artifacts.
        // 64 may have artifacts but is faster.
        // Less important if we can turn metatiling on.
        //
        // defaults to 128 as of tilelive-mapnik@0.3.2
        //
        bufferSize: 64
    });
}

module.exports = MapnikFactory;


MapnikFactory.prototype.getRenderer = function(mapConfig, params, format, layer, callback) {
    var self = this;
    var mml_builder;

    params = _.defaults(params, this.mapConfigToMMLBuilderConfig(mapConfig));

    var scaleFactor = _.isUndefined(params.scale_factor) ? 1 : +params.scale_factor,
        tileSize = this.tile_scale_factors[scaleFactor];

    if (!tileSize) {
        var err = new Error('Tile with specified resolution not found');
        err.http_status = 404;
        return callback(err);
    }

    step(
        function initBuilder() {
            // create an mapnik mml builder object
            mml_builder = self._mmlStore.mml_builder(params, this);
        },
        function generateXML(err) {
            assert.ifError(err);
            mml_builder.toXML(this);
        },
        function loadMapnik(err, xml) {
            assert.ifError(err);

            var query = {
                metatile: self._mapnik_opts.metatile,
                bufferSize: self._mapnik_opts.bufferSize,
                poolSize: self._mapnik_opts.poolSize,
                scale: scaleFactor,
                tileSize: tileSize,
                autoLoadFonts: false,
                internal_cache: false
            };

            // build full document to pass to tilelive
            var uri = {
                query: query,
                protocol: 'mapnik:',
                xml: xml,
                strict: !!params.strict // force boolean
            };

            // hand off to tilelive to create a renderer
{'fraction_non_alphanumeric': 0.09390538428754085, 'fraction_numerical': 0.00823980679073732, 'mean_word_length': 2.1740306582506763, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 7}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2388882', 'n_tokens_mistral': 2063, 'n_tokens_neox': 1958, 'n_words': 553}