| 
/* 
 | 
* Licensed to the Apache Software Foundation (ASF) under one 
 | 
* or more contributor license agreements.  See the NOTICE file 
 | 
* distributed with this work for additional information 
 | 
* regarding copyright ownership.  The ASF licenses this file 
 | 
* to you under the Apache License, Version 2.0 (the 
 | 
* "License"); you may not use this file except in compliance 
 | 
* with the License.  You may obtain a copy of the License at 
 | 
* 
 | 
*   http://www.apache.org/licenses/LICENSE-2.0 
 | 
* 
 | 
* Unless required by applicable law or agreed to in writing, 
 | 
* software distributed under the License is distributed on an 
 | 
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 | 
* KIND, either express or implied.  See the License for the 
 | 
* specific language governing permissions and limitations 
 | 
* under the License. 
 | 
*/ 
 | 
  
 | 
  
 | 
/** 
 | 
 * AUTO-GENERATED FILE. DO NOT MODIFY. 
 | 
 */ 
 | 
  
 | 
/* 
 | 
* Licensed to the Apache Software Foundation (ASF) under one 
 | 
* or more contributor license agreements.  See the NOTICE file 
 | 
* distributed with this work for additional information 
 | 
* regarding copyright ownership.  The ASF licenses this file 
 | 
* to you under the Apache License, Version 2.0 (the 
 | 
* "License"); you may not use this file except in compliance 
 | 
* with the License.  You may obtain a copy of the License at 
 | 
* 
 | 
*   http://www.apache.org/licenses/LICENSE-2.0 
 | 
* 
 | 
* Unless required by applicable law or agreed to in writing, 
 | 
* software distributed under the License is distributed on an 
 | 
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 | 
* KIND, either express or implied.  See the License for the 
 | 
* specific language governing permissions and limitations 
 | 
* under the License. 
 | 
*/ 
 | 
import { parseSVG, makeViewBoxTransform } from 'zrender/lib/tool/parseSVG.js'; 
 | 
import Group from 'zrender/lib/graphic/Group.js'; 
 | 
import Rect from 'zrender/lib/graphic/shape/Rect.js'; 
 | 
import { assert, createHashMap, each } from 'zrender/lib/core/util.js'; 
 | 
import BoundingRect from 'zrender/lib/core/BoundingRect.js'; 
 | 
import { parseXML } from 'zrender/lib/tool/parseXML.js'; 
 | 
import { GeoSVGRegion } from './Region.js'; 
 | 
/** 
 | 
 * "region available" means that: enable users to set attribute `name="xxx"` on those tags 
 | 
 * to make it be a region. 
 | 
 * 1. region styles and its label styles can be defined in echarts opton: 
 | 
 * ```js 
 | 
 * geo: { 
 | 
 *     regions: [{ 
 | 
 *         name: 'xxx', 
 | 
 *         itemStyle: { ... }, 
 | 
 *         label: { ... } 
 | 
 *     }, { 
 | 
 *         ... 
 | 
 *     }, 
 | 
 *     ...] 
 | 
 * }; 
 | 
 * ``` 
 | 
 * 2. name can be duplicated in different SVG tag. All of the tags with the same name share 
 | 
 * a region option. For exampel if there are two <path> representing two lung lobes. They have 
 | 
 * no common parents but both of them need to display label "lung" inside. 
 | 
 */ 
 | 
var REGION_AVAILABLE_SVG_TAG_MAP = createHashMap(['rect', 'circle', 'line', 'ellipse', 'polygon', 'polyline', 'path', 
 | 
// <text> <tspan> are also enabled because some SVG might paint text itself, 
 | 
// but still need to trigger events or tooltip. 
 | 
'text', 'tspan', 
 | 
// <g> is also enabled because this case: if multiple tags share one name 
 | 
// and need label displayed, every tags will display the name, which is not 
 | 
// expected. So we can put them into a <g name="xxx">. Thereby only one label 
 | 
// displayed and located based on the bounding rect of the <g>. 
 | 
'g']); 
 | 
var GeoSVGResource = /** @class */function () { 
 | 
  function GeoSVGResource(mapName, svg) { 
 | 
    this.type = 'geoSVG'; 
 | 
    // All used graphics. key: hostKey, value: root 
 | 
    this._usedGraphicMap = createHashMap(); 
 | 
    // All unused graphics. 
 | 
    this._freedGraphics = []; 
 | 
    this._mapName = mapName; 
 | 
    // Only perform parse to XML object here, which might be time 
 | 
    // consiming for large SVG. 
 | 
    // Although convert XML to zrender element is also time consiming, 
 | 
    // if we do it here, the clone of zrender elements has to be 
 | 
    // required. So we do it once for each geo instance, util real 
 | 
    // performance issues call for optimizing it. 
 | 
    this._parsedXML = parseXML(svg); 
 | 
  } 
 | 
  GeoSVGResource.prototype.load = function /* nameMap: NameMap */ 
 | 
  () { 
 | 
    // In the "load" stage, graphic need to be built to 
 | 
    // get boundingRect for geo coordinate system. 
 | 
    var firstGraphic = this._firstGraphic; 
 | 
    // Create the return data structure only when first graphic created. 
 | 
    // Because they will be used in geo coordinate system update stage, 
 | 
    // and `regions` will be mounted at `geo` coordinate system, 
 | 
    // in which there is no "view" info, so that it should better not to 
 | 
    // make references to graphic elements. 
 | 
    if (!firstGraphic) { 
 | 
      firstGraphic = this._firstGraphic = this._buildGraphic(this._parsedXML); 
 | 
      this._freedGraphics.push(firstGraphic); 
 | 
      this._boundingRect = this._firstGraphic.boundingRect.clone(); 
 | 
      // PENDING: `nameMap` will not be supported until some real requirement come. 
 | 
      // if (nameMap) { 
 | 
      //     named = applyNameMap(named, nameMap); 
 | 
      // } 
 | 
      var _a = createRegions(firstGraphic.named), 
 | 
        regions = _a.regions, 
 | 
        regionsMap = _a.regionsMap; 
 | 
      this._regions = regions; 
 | 
      this._regionsMap = regionsMap; 
 | 
    } 
 | 
    return { 
 | 
      boundingRect: this._boundingRect, 
 | 
      regions: this._regions, 
 | 
      regionsMap: this._regionsMap 
 | 
    }; 
 | 
  }; 
 | 
  GeoSVGResource.prototype._buildGraphic = function (svgXML) { 
 | 
    var result; 
 | 
    var rootFromParse; 
 | 
    try { 
 | 
      result = svgXML && parseSVG(svgXML, { 
 | 
        ignoreViewBox: true, 
 | 
        ignoreRootClip: true 
 | 
      }) || {}; 
 | 
      rootFromParse = result.root; 
 | 
      assert(rootFromParse != null); 
 | 
    } catch (e) { 
 | 
      throw new Error('Invalid svg format\n' + e.message); 
 | 
    } 
 | 
    // Note: we keep the covenant that the root has no transform. So always add an extra root. 
 | 
    var root = new Group(); 
 | 
    root.add(rootFromParse); 
 | 
    root.isGeoSVGGraphicRoot = true; 
 | 
    // [THE_RULE_OF_VIEWPORT_AND_VIEWBOX] 
 | 
    // 
 | 
    // Consider: `<svg width="..." height="..." viewBox="...">` 
 | 
    // - the `width/height` we call it `svgWidth/svgHeight` for short. 
 | 
    // - `(0, 0, svgWidth, svgHeight)` defines the viewport of the SVG, or say, 
 | 
    //   "viewport boundingRect", or `boundingRect` for short. 
 | 
    // - `viewBox` defines the transform from the real content ot the viewport. 
 | 
    //   `viewBox` has the same unit as the content of SVG. 
 | 
    //   If `viewBox` exists, a transform is defined, so the unit of `svgWidth/svgHeight` become 
 | 
    //   different from the content of SVG. Otherwise, they are the same. 
 | 
    // 
 | 
    // If both `svgWidth/svgHeight/viewBox` are specified in a SVG file, the transform rule will be: 
 | 
    // 0. `boundingRect` is `(0, 0, svgWidth, svgHeight)`. Set it to Geo['_rect'] (View['_rect']). 
 | 
    // 1. Make a transform from `viewBox` to `boundingRect`. 
 | 
    //    Note: only support `preserveAspectRatio 'xMidYMid'` here. That is, this transform will preserve 
 | 
    //    the aspect ratio. 
 | 
    // 2. Make a transform from boundingRect to Geo['_viewRect'] (View['_viewRect']) 
 | 
    //    (`Geo`/`View` will do this job). 
 | 
    //    Note: this transform might not preserve aspect radio, which depending on how users specify 
 | 
    //    viewRect in echarts option (e.g., `geo.left/top/width/height` will not preserve aspect ratio, 
 | 
    //    but `geo.layoutCenter/layoutSize` will preserve aspect ratio). 
 | 
    // 
 | 
    // If `svgWidth/svgHeight` not specified, we use `viewBox` as the `boundingRect` to make the SVG 
 | 
    // layout look good. 
 | 
    // 
 | 
    // If neither `svgWidth/svgHeight` nor `viewBox` are not specified, we calculate the boundingRect 
 | 
    // of the SVG content and use them to make SVG layout look good. 
 | 
    var svgWidth = result.width; 
 | 
    var svgHeight = result.height; 
 | 
    var viewBoxRect = result.viewBoxRect; 
 | 
    var boundingRect = this._boundingRect; 
 | 
    if (!boundingRect) { 
 | 
      var bRectX = void 0; 
 | 
      var bRectY = void 0; 
 | 
      var bRectWidth = void 0; 
 | 
      var bRectHeight = void 0; 
 | 
      if (svgWidth != null) { 
 | 
        bRectX = 0; 
 | 
        bRectWidth = svgWidth; 
 | 
      } else if (viewBoxRect) { 
 | 
        bRectX = viewBoxRect.x; 
 | 
        bRectWidth = viewBoxRect.width; 
 | 
      } 
 | 
      if (svgHeight != null) { 
 | 
        bRectY = 0; 
 | 
        bRectHeight = svgHeight; 
 | 
      } else if (viewBoxRect) { 
 | 
        bRectY = viewBoxRect.y; 
 | 
        bRectHeight = viewBoxRect.height; 
 | 
      } 
 | 
      // If both viewBox and svgWidth/svgHeight not specified, 
 | 
      // we have to determine how to layout those element to make them look good. 
 | 
      if (bRectX == null || bRectY == null) { 
 | 
        var calculatedBoundingRect = rootFromParse.getBoundingRect(); 
 | 
        if (bRectX == null) { 
 | 
          bRectX = calculatedBoundingRect.x; 
 | 
          bRectWidth = calculatedBoundingRect.width; 
 | 
        } 
 | 
        if (bRectY == null) { 
 | 
          bRectY = calculatedBoundingRect.y; 
 | 
          bRectHeight = calculatedBoundingRect.height; 
 | 
        } 
 | 
      } 
 | 
      boundingRect = this._boundingRect = new BoundingRect(bRectX, bRectY, bRectWidth, bRectHeight); 
 | 
    } 
 | 
    if (viewBoxRect) { 
 | 
      var viewBoxTransform = makeViewBoxTransform(viewBoxRect, boundingRect); 
 | 
      // Only support `preserveAspectRatio 'xMidYMid'` 
 | 
      rootFromParse.scaleX = rootFromParse.scaleY = viewBoxTransform.scale; 
 | 
      rootFromParse.x = viewBoxTransform.x; 
 | 
      rootFromParse.y = viewBoxTransform.y; 
 | 
    } 
 | 
    // SVG needs to clip based on `viewBox`. And some SVG files really rely on this feature. 
 | 
    // They do not strictly confine all of the content inside a display rect, but deliberately 
 | 
    // use a `viewBox` to define a displayable rect. 
 | 
    // PENDING: 
 | 
    // The drawback of the `setClipPath` here is: the region label (genereted by echarts) near the 
 | 
    // edge might also be clipped, because region labels are put as `textContent` of the SVG path. 
 | 
    root.setClipPath(new Rect({ 
 | 
      shape: boundingRect.plain() 
 | 
    })); 
 | 
    var named = []; 
 | 
    each(result.named, function (namedItem) { 
 | 
      if (REGION_AVAILABLE_SVG_TAG_MAP.get(namedItem.svgNodeTagLower) != null) { 
 | 
        named.push(namedItem); 
 | 
        setSilent(namedItem.el); 
 | 
      } 
 | 
    }); 
 | 
    return { 
 | 
      root: root, 
 | 
      boundingRect: boundingRect, 
 | 
      named: named 
 | 
    }; 
 | 
  }; 
 | 
  /** 
 | 
   * Consider: 
 | 
   * (1) One graphic element can not be shared by different `geoView` running simultaneously. 
 | 
   *     Notice, also need to consider multiple echarts instances share a `mapRecord`. 
 | 
   * (2) Converting SVG to graphic elements is time consuming. 
 | 
   * (3) In the current architecture, `load` should be called frequently to get boundingRect, 
 | 
   *     and it is called without view info. 
 | 
   * So we maintain graphic elements in this module, and enables `view` to use/return these 
 | 
   * graphics from/to the pool with it's uid. 
 | 
   */ 
 | 
  GeoSVGResource.prototype.useGraphic = function (hostKey /* , nameMap: NameMap */) { 
 | 
    var usedRootMap = this._usedGraphicMap; 
 | 
    var svgGraphic = usedRootMap.get(hostKey); 
 | 
    if (svgGraphic) { 
 | 
      return svgGraphic; 
 | 
    } 
 | 
    svgGraphic = this._freedGraphics.pop() 
 | 
    // use the first boundingRect to avoid duplicated boundingRect calculation. 
 | 
    || this._buildGraphic(this._parsedXML); 
 | 
    usedRootMap.set(hostKey, svgGraphic); 
 | 
    // PENDING: `nameMap` will not be supported until some real requirement come. 
 | 
    // `nameMap` can only be obtained from echarts option. 
 | 
    // The original `named` must not be modified. 
 | 
    // if (nameMap) { 
 | 
    //     svgGraphic = extend({}, svgGraphic); 
 | 
    //     svgGraphic.named = applyNameMap(svgGraphic.named, nameMap); 
 | 
    // } 
 | 
    return svgGraphic; 
 | 
  }; 
 | 
  GeoSVGResource.prototype.freeGraphic = function (hostKey) { 
 | 
    var usedRootMap = this._usedGraphicMap; 
 | 
    var svgGraphic = usedRootMap.get(hostKey); 
 | 
    if (svgGraphic) { 
 | 
      usedRootMap.removeKey(hostKey); 
 | 
      this._freedGraphics.push(svgGraphic); 
 | 
    } 
 | 
  }; 
 | 
  return GeoSVGResource; 
 | 
}(); 
 | 
export { GeoSVGResource }; 
 | 
function setSilent(el) { 
 | 
  // Only named element has silent: false, other elements should 
 | 
  // act as background and has no user interaction. 
 | 
  el.silent = false; 
 | 
  // text|tspan will be converted to group. 
 | 
  if (el.isGroup) { 
 | 
    el.traverse(function (child) { 
 | 
      child.silent = false; 
 | 
    }); 
 | 
  } 
 | 
} 
 | 
function createRegions(named) { 
 | 
  var regions = []; 
 | 
  var regionsMap = createHashMap(); 
 | 
  // Create resions only for the first graphic. 
 | 
  each(named, function (namedItem) { 
 | 
    // Region has feature to calculate center for tooltip or other features. 
 | 
    // If there is a <g name="xxx">, the center should be the center of the 
 | 
    // bounding rect of the g. 
 | 
    if (namedItem.namedFrom != null) { 
 | 
      return; 
 | 
    } 
 | 
    var region = new GeoSVGRegion(namedItem.name, namedItem.el); 
 | 
    // PENDING: if `nameMap` supported, this region can not be mounted on 
 | 
    // `this`, but can only be created each time `load()` called. 
 | 
    regions.push(region); 
 | 
    // PENDING: if multiple tag named with the same name, only one will be 
 | 
    // found by `_regionsMap`. `_regionsMap` is used to find a coordinate 
 | 
    // by name. We use `region.getCenter()` as the coordinate. 
 | 
    regionsMap.set(namedItem.name, region); 
 | 
  }); 
 | 
  return { 
 | 
    regions: regions, 
 | 
    regionsMap: regionsMap 
 | 
  }; 
 | 
} 
 | 
// PENDING: `nameMap` will not be supported until some real requirement come. 
 | 
// /** 
 | 
//  * Use the alias in geoNameMap. 
 | 
//  * The input `named` must not be modified. 
 | 
//  */ 
 | 
// function applyNameMap( 
 | 
//     named: GeoSVGGraphicRecord['named'], 
 | 
//     nameMap: NameMap 
 | 
// ): GeoSVGGraphicRecord['named'] { 
 | 
//     const result = [] as GeoSVGGraphicRecord['named']; 
 | 
//     for (let i = 0; i < named.length; i++) { 
 | 
//         let regionGraphic = named[i]; 
 | 
//         const name = regionGraphic.name; 
 | 
//         if (nameMap && nameMap.hasOwnProperty(name)) { 
 | 
//             regionGraphic = extend({}, regionGraphic); 
 | 
//             regionGraphic.name = name; 
 | 
//         } 
 | 
//         result.push(regionGraphic); 
 | 
//     } 
 | 
//     return result; 
 | 
// } 
 |