text: // @flow
  
  import {
      Uniform1i,
      Uniform1f,
      Uniform2f,
      UniformMatrix4f
  } from '../uniform_binding';
  import {extend} from '../../util/util';
  import browser from '../../util/browser';
  
  import type Context from '../../gl/context';
  import type Painter from '../painter';
  import type {UniformValues, UniformLocations} from '../uniform_binding';
  
  export type SymbolIconUniformsType = {|
      'u_is_size_zoom_constant': Uniform1i,
      'u_is_size_feature_constant': Uniform1i,
      'u_size_t': Uniform1f,
      'u_size': Uniform1f,
      'u_camera_to_center_distance': Uniform1f,
      'u_pitch': Uniform1f,
      'u_rotate_symbol': Uniform1i,
      'u_aspect_ratio': Uniform1f,
      'u_fade_change': Uniform1f,
      'u_matrix': UniformMatrix4f,
      'u_label_plane_matrix': UniformMatrix4f,
      'u_coord_matrix': UniformMatrix4f,
      'u_is_text': Uniform1i,
      'u_pitch_with_map': Uniform1i,
      'u_texsize': Uniform2f,
      'u_texture': Uniform1i
  |};
  
  export type SymbolSDFUniformsType = {|
      'u_is_size_zoom_constant': Uniform1i,
      'u_is_size_feature_constant': Uniform1i,
      'u_size_t': Uniform1f,
      'u_size': Uniform1f,
      'u_camera_to_center_distance': Uniform1f,
      'u_pitch': Uniform1f,
      'u_rotate_symbol': Uniform1i,
      'u_aspect_ratio': Uniform1f,
      'u_fade_change': Uniform1f,
      'u_matrix': UniformMatrix4f,
      'u_label_plane_matrix': UniformMatrix4f,
      'u_coord_matrix': UniformMatrix4f,
      'u_is_text': Uniform1i,
      'u_pitch_with_map': Uniform1i,
      'u_texsize': Uniform2f,
      'u_texture': Uniform1i,
      'u_gamma_scale': Uniform1f,
      'u_device_pixel_ratio': Uniform1f,
      'u_is_halo': Uniform1i
  |};
  
  export type symbolTextAndIconUniformsType = {|
      'u_is_size_zoom_constant': Uniform1i,
      'u_is_size_feature_constant': Uniform1i,
      'u_size_t': Uniform1f,
      'u_size': Uniform1f,
      'u_camera_to_center_distance': Uniform1f,
      'u_pitch': Uniform1f,
      'u_rotate_symbol': Uniform1i,
      'u_aspect_ratio': Uniform1f,
      'u_fade_change': Uniform1f,
      'u_matrix': UniformMatrix4f,
      'u_label_plane_matrix': UniformMatrix4f,
      'u_coord_matrix': UniformMatrix4f,
      'u_is_text': Uniform1i,
      'u_pitch_with_map': Uniform1i,
      'u_texsize': Uniform2f,
      'u_texsize_icon': Uniform2f,
      'u_texture': Uniform1i,
      'u_texture_icon': Uniform1i,
      'u_gamma_scale': Uniform1f,
      'u_device_pixel_ratio': Uniform1f,
      'u_is_halo': Uniform1i
  |};
  
  export type SymbolDefinesType = 'PITCH_WITH_MAP_TERRAIN';
  
  const symbolIconUniforms = (context: Context, locations: UniformLocations): SymbolIconUniformsType => ({
      'u_is_size_zoom_constant': new Uniform1i(context, locations.u_is_size_zoom_constant),
      'u_is_size_feature_constant': new Uniform1i(context, locations.u_is_size_feature_constant),
      'u_size_t': new Uniform1f(context, locations.u_size_t),
      'u_size': new Uniform1f(context, locations.u_size),
      'u_camera_to_center_distance': new Uniform1f(context, locations.u_camera_to_center_distance),
      'u_pitch': new Uniform1f(context, locations.u_pitch),
      'u_rotate_symbol': new Uniform1i(context, locations.u_rotate_symbol),
      'u_aspect_ratio': new Uniform1f(context, locations.u_aspect_ratio),
      'u_fade_change': new Uniform1f(context, locations.u_fade_change),
      'u_matrix': new UniformMatrix4f(context, locations.u_matrix),
      'u_label_plane_matrix': new UniformMatrix4f(context, locations.u_label_plane_matrix),
      'u_coord_matrix': new UniformMatrix4f(context, locations.u_coord_matrix),
      'u_is_text': new Uniform1i(context, locations.u_is_text),
      'u_pitch_with_map': new Uniform1i(context, locations.u_pitch_with_map),
      'u_texsize': new Uniform2f(context, locations.u_texsize),
      'u_texture': new Uniform1i(context, locations.u_texture)
  });
  
  const symbolSDFUniforms = (context: Context, locations: UniformLocations): SymbolSDFUniformsType => ({
      'u_is_size_zoom_constant': new Uniform1i(context, locations.u_is_size_zoom_constant),
      'u_is_size_feature_constant': new Uniform1i(context, locations.u_is_size_feature_constant),
      'u_size_t': new Uniform1f(context, locations.u_size_t),
      'u_size': new Uniform1f(context, locations.u_size),
      'u_camera_to_center_distance': new Uniform1f(context, locations.u_camera_to_center_distance),
      'u_pitch': new Uniform1f(context, locations.u_pitch),
      'u_rotate_symbol': new Uniform1i(context, locations.u_rotate_symbol),
      'u_aspect_ratio': new Uniform1f(context, locations.u_aspect_ratio),
      'u_fade_change': new Uniform1f(context, locations.u_fade_change),
      'u_matrix': new UniformMatrix4f(context, locations.u_matrix),
      'u_label_plane_matrix': new UniformMatrix4f(context, locations.u_label_plane_matrix),
      'u_coord_matrix': new UniformMatrix4f(context, locations.u_coord_matrix),
      'u_is_text': new Uniform1i(context, locations.u_is_text),
      'u_pitch_with_map': new Uniform1i(context, locations.u_pitch_with_map),
      'u_texsize': new Uniform2f(context, locations.u_texsize),
      'u_texture': new Uniform1i(context, locations.u_texture),
      'u_gamma_scale': new Uniform1f(context, locations.u_gamma_scale),
      'u_device_pixel_ratio': new Uniform1f(context, locations.u_device_pixel_ratio),
      'u_is_halo': new Uniform1i(context, locations.u_is_halo)
  });
  
  const symbolTextAndIconUniforms = (context: Context, locations: UniformLocations): symbolTextAndIconUniformsType => ({
      'u_is_size_zoom_constant': new Uniform1i(context, locations.u_is_size_zoom_constant),
      'u_is_size_feature_constant': new Uniform1i(context, locations.u_is_size_feature_constant),
      'u_size_t': new Uniform1f(context, locations.u_size_t),
      'u_size': new Uniform1f(context, locations.u_size),
      'u_camera_to_center_distance': new Uniform1f(context, locations.u_camera_to_center_distance),
      'u_pitch': new Uniform1f(context, locations.u_pitch),
      'u_rotate_symbol': new Uniform1i(context, locations.u_rotate_symbol),
      'u_aspect_ratio': new Uniform1f(context, locations.u_aspect_ratio),
      'u_fade_change': new Uniform1f(context, locations.u_fade_change),
      'u_matrix': new UniformMatrix4f(context, locations.u_matrix),
      'u_label_plane_matrix': new UniformMatrix4f(context, locations.u_label_plane_matrix),
      'u_coord_matrix': new UniformMatrix4f(context, locations.u_coord_matrix),
      'u_is_text': new Uniform1i(context, locations.u_is_text),
      'u_pitch_with_map': new Uniform1i(context, locations.u_pitch_with_map),
      'u_texsize': new Uniform2f(context, locations.u_texsize),
      'u_texsize_icon': new Uniform2f(context, locations.u_texsize_icon),
      'u_texture': new Uniform1i(context, locations.u_texture),
      'u_texture_icon': new Uniform1i(context, locations.u_texture_icon),
      'u_gamma_scale': new Uniform1f(context, locations.u_gamma_scale),
      'u_device_pixel_ratio': new Uniform1f(context, locations.u_device_pixel_ratio),
      'u_is_halo': new Uniform1i(context, locations.u_is_halo)
  });
  
  const symbolIconUniformValues = (
      functionType: string,
      size: ?{uSizeT: number, uSize: number},
      rotateInShader: boolean,
      pitchWithMap: boolean,
      painter: Painter,
      matrix: Float32Array,
      labelPlaneMatrix: Float32Array,
      glCoordMatrix: Float32Array,
      isText: boolean,
      texSize: [number, number]
  ): UniformValues<SymbolIconUniformsType> => {
      const transform = painter.transform;
  
      return {
          'u_is_size_zoom_constant': +(functionType === 'constant' || functionType === 'source'),
          'u_is_size_feature_constant': +(functionType === 'constant' || functionType === 'camera'),
          'u_size_t': size ? size.uSizeT : 0,
          'u_size': size ? size.uSize : 0,
          'u_camera_to_center_distance': transform.cameraToCenterDistance,
          'u_pitch': transform.pitch / 360 * 2 * Math.PI,
          'u_rotate_symbol': +rotateInShader,
          'u_aspect_ratio': transform.width / transform.height,
          'u_fade_change': painter.options.fadeDuration ? painter.symbolFadeChange : 1,
          'u_matrix': matrix,
          'u_label_plane_matrix': labelPlaneMatrix,
          'u_coord_matrix': glCoordMatrix,
          'u_is_text': +isText,
          'u_pitch_with_map': +pitchWithMap,
          'u_texsize': texSize,
          'u_texture': 0
      };
  };
  
  const symbolSDFUniformValues = (
      functionType: string,
      size: ?{uSizeT: number, uSize: number},
      rotateInShader: boolean,
      pitchWithMap: boolean,
      painter: Painter,
      matrix: Float32Array,
      labelPlaneMatrix: Float32Array,
      glCoordMatrix: Float32Array,
      isText: boolean,
      texSize: [number, number],
      isHalo: boolean
  ): UniformValues<SymbolSDFUniformsType> => {
      const transform = painter.transform;
  
      return extend(symbolIconUniformValues(functionType, size,
          rotateInShader, pitchWithMap, painter, matrix, labelPlaneMatrix,
          glCoordMatrix, isText, texSize), {
          'u_gamma_scale': (pitchWithMap ? Math.cos(transform._pitch) * transform.cameraToCenterDistance : 1),
          'u_device_pixel_ratio': browser.devicePixelRatio,
          'u_is_halo': +isHalo
      });
  };
  
  const symbolTextAndIconUniformValues = (
      functionType: string,
      size: ?{uSizeT: number, uSize: number},
      rotateInShader: boolean,
      pitchWithMap: boolean,
      painter: Painter,
      matrix: Float32Array,
      labelPlaneMatrix: Float32Array,
      glCoordMatrix: Float32Array,
      texSizeSDF: [number, number],
      texSizeIcon: [number, number]
  ): UniformValues<SymbolIconUniformsType> => {
      return extend(symbolSDFUniformValues(functionType, size,
          rotateInShader, pitchWithMap, painter, matrix, labelPlaneMatrix,
          glCoordMatrix, true, texSizeSDF, true), {
          'u_texsize_icon': texSizeIcon,
          'u_texture_icon': 1
      });
  };
  
  export {symbolIconUniforms, symbolSDFUniforms, symbolIconUniformValues, symbolSDFUniformValues, symbolTextAndIconUniformValues, symbolTextAndIconUniforms};
  