{"version":3,"file":"videoEntity-eRfPSbwL.cjs","names":["isDataUrl","isOffscreenCanvasSupported","isDataUrl","EScaleMode","isAndroid","isIOS","getTextByMaxWidth"],"sources":["../src/player/render/common/mCache.ts","../src/player/render/common/renderCache.ts","../src/player/render/common/videoEntity.ts"],"sourcesContent":["import {logger} from 'src/helper/logger'\n// import VideoEntity from './videoEntity'\nimport {isDataUrl} from 'src/helper/utils'\nimport type {AnimatorType} from 'src/player/video/animator'\nimport type {MixEvideoOptions} from 'src/type/mix'\n// import EVideo from 'src/player'\nexport type MCacheItem = {\n  [frames: number]: ImageBitmap | HTMLImageElement | undefined\n}\n//\nfunction setStoreName(op: MixEvideoOptions) {\n  const {effects, mode, container} = op\n  let storeName = isDataUrl(op.videoSource) ? op.videoSource.substring(22, 88) : op.videoSource\n  // let storeName = op.videoSource\n  if (effects) {\n    const eUrl = Object.keys(effects)\n      .map(key => key + '=' + effects[key])\n      .join('&')\n    storeName += eUrl.indexOf('?') > -1 ? '&' : '?'\n    storeName += eUrl\n  }\n  if (container && container.clientHeight) {\n    storeName += `${storeName.indexOf('?') > -1 ? '&' : '?'}mode=${mode}&height=${container.clientHeight}&width=${\n      container.clientWidth\n    }`\n  }\n  storeName = storeName.replace(/\\s+/g, '')\n  // console.log(`storeName`, storeName)\n  return storeName\n}\n//\nexport default class MCache {\n  //=== 帧缓存组合 用 静态类 临时存储\n  static caches: {[url: string]: MCacheItem} = {}\n  static cacheKeys: string[] = []\n  static cachesOfs: {[url: string]: HTMLCanvasElement | OffscreenCanvas} = {}\n  //===\n  private storeName: string\n  private op: MixEvideoOptions\n  // currentFrame = -1\n  private frameCacheCount = 5\n  private requestAnimationFramePercent = 0.95\n  private hasRequestAnimationFrame = false\n  //\n  private animationType: AnimatorType\n  private fps = 0\n  private videoDurationTime = 0\n  //\n  constructor(op: MixEvideoOptions) {\n    if (!op.videoSource || !op.useFrameCache) return\n    this.op = op\n    this.storeName = setStoreName(op)\n    if (!MCache.caches[this.storeName]) {\n      logger.debug('[mCache]', '[实例化]')\n      MCache.caches[this.storeName] = {}\n      MCache.cacheKeys.push(this.storeName)\n    }\n    if (typeof op.useFrameCache === 'number' && op.useFrameCache > 0) {\n      this.frameCacheCount = op.useFrameCache\n    }\n    logger.debug(`[mcache]`, `[constructor]`, `设置缓存数`, this.frameCacheCount, `缓存视频`, MCache.cacheKeys)\n    logger.debug(`[mcache]`, this.storeName, `当前缓存帧数 ${Object.keys(MCache.caches[this.storeName] || {}).length}`)\n  }\n  setOptions({fps, animationType, videoDurationTime}: any) {\n    this.fps = fps\n    this.animationType = animationType\n    this.videoDurationTime = videoDurationTime\n    logger.debug(`[mcache]`, {fps, animationType, videoDurationTime})\n  }\n  public async setup() {\n    this.setAnimationStatus()\n  }\n  setAnimationStatus() {\n    if (\n      this.animationType !== 'requestVideoFrameCallback' &&\n      Object.keys(MCache.caches[this.storeName] || {}).length > 0\n    ) {\n      this.hasRequestAnimationFrame = true\n    }\n    logger.debug('[mCache]', '[setAnimationStatus]', 'hasRequestAnimationFrame', this.hasRequestAnimationFrame)\n  }\n  isCache() {\n    return Object.keys(MCache.caches[this.storeName]).length > 0\n  }\n  get() {\n    return MCache.caches[this.storeName]\n  }\n  set(d: MCacheItem) {\n    MCache.caches[this.storeName] = d\n  }\n  getFrame(frame: number) {\n    // 不补全遗留帧 避免抖动，考虑是否 requestVideoFrameCallback 也需要这样操作\n    if (this.hasRequestAnimationFrame) {\n      // if (frame === this.currentFrame) {\n      //   // console.log('=== skip ========================')\n      //   return 'skip'\n      // }\n      // console.log('hasRequestAnimationFrame skip', frame)\n      // this.currentFrame = frame\n      return MCache.caches[this.storeName] && MCache.caches[this.storeName][frame]\n        ? MCache.caches[this.storeName][frame]\n        : 'skip'\n    }\n    // if (frame === this.currentFrame) {\n    //   // console.log('=== skip ========================')\n    //   return 'skip'\n    // }\n    // console.log('<<< get frame', frame, this.currentFrame)\n    // this.currentFrame = frame\n    return MCache.caches[this.storeName] ? MCache.caches[this.storeName][frame] : undefined\n  }\n  setFrame(frame: number, d: ImageBitmap | HTMLImageElement) {\n    // console.log('MCache.caches[this.storeName]', MCache.caches[this.storeName], this.storeName)\n    if (d && !MCache.caches[this.storeName][frame] && !this.hasRequestAnimationFrame) {\n      // console.log('>>> set frame', frame)\n      MCache.caches[this.storeName][frame] = d\n    }\n  }\n  private checkCache() {\n    if (this.animationType !== 'requestVideoFrameCallback') {\n      const frameCount = this.videoDurationTime * this.fps\n      let needCacheFrameCount = frameCount * this.requestAnimationFramePercent\n      //防止边界问题导致经常删除缓存\n      needCacheFrameCount = Math.round(needCacheFrameCount)\n      const cacheItem = MCache.caches[this.storeName] || {}\n      logger.debug(\n        '[mCache]',\n        '[checkCache] 当前缓存帧数',\n        Object.keys(cacheItem).length,\n        '需要缓存帧数',\n        needCacheFrameCount,\n        '缓存总数',\n        frameCount,\n      )\n      if (cacheItem && Object.keys(cacheItem).length < needCacheFrameCount) {\n        this.removeCacheItem(this.storeName)\n        logger.debug('[mCache]', '[checkCache] removeCacheItem', this.storeName)\n      }\n    }\n  }\n  //TODO 定制批量删除策略\n  removeCache() {\n    //超过 frameCacheCount 删除\n    if (MCache.cacheKeys && MCache.cacheKeys.length > this.frameCacheCount) {\n      const resetCount = MCache.cacheKeys.length - this.frameCacheCount\n      for (let i = 1; i < resetCount; i++) {\n        const key = MCache.cacheKeys.shift()\n        // logger.debug('[removeCache]', key, MCache.cacheKeys)\n        this.removeCacheItem(key)\n        logger.debug('[mCache]', '[removeCache]', '达到视频缓存总数删除', key)\n      }\n    }\n  }\n  removeCacheItem(key) {\n    if (MCache.caches[key]) {\n      delete MCache.caches[key]\n      MCache.caches[key] = {}\n    }\n    const cacheKeyIndex = MCache.cacheKeys.indexOf(key)\n    if (cacheKeyIndex > -1) {\n      MCache.cacheKeys.splice(cacheKeyIndex, 1)\n    }\n    // canvas remove\n    /*\n    let canvas = MCache.cachesOfs[key]\n    if (canvas) {\n      if (canvas instanceof HTMLCanvasElement) {\n        canvas.remove()\n        canvas = undefined\n      } else {\n        MCache.cachesOfs[key] = undefined\n      }\n    }*/\n  }\n  public videoSeekedEvent() {\n    this.checkCache()\n    this.setAnimationStatus()\n  }\n  public destroy() {\n    logger.debug('[mCache]', '[destroy]')\n    this.removeCache()\n    this.checkCache()\n  }\n}\n","import MCache from 'src/player/render/common/mCache'\nimport type {MixEvideoOptions} from 'src/type/mix'\nclass RenderCache {\n  private canvas: HTMLCanvasElement | OffscreenCanvas\n  private op: MixEvideoOptions\n  mCache: MCache\n  constructor(canvas: HTMLCanvasElement | OffscreenCanvas, op: MixEvideoOptions) {\n    this.canvas = canvas\n    this.op = op\n    this.mCache = new MCache(this.op)\n  }\n  isCache() {\n    return this.mCache.isCache()\n  }\n  setCache(frame: number) {\n    // if (!this.op.loop && !this.op.useFrameCache) return\n    if (!this.op.useFrameCache) return\n    this.createFramesCache(frame)\n  }\n  getCache(frame: number) {\n    // if (!this.op.loop && !this.op.useFrameCache) return undefined\n    if (!this.op.useFrameCache) return undefined\n    return this.mCache.getFrame(frame)\n  }\n  /**\n   * 注销缓存\n   */\n  public destroy() {\n    this.mCache.destroy()\n  }\n  /**\n   * 申请缓存\n   */\n  public async setup() {\n    if (this.op.useFrameCache) await this.mCache.setup()\n  }\n  private async createFramesCache(frame: number) {\n    // console.log('[mcache][this.canvas]', this.canvas)\n    if (!this.canvas) return\n    // if (!!self.OffscreenCanvas && this.canvas instanceof OffscreenCanvas) {\n    //   const bitmap = this.canvas.transferToImageBitmap()\n    //   // const blob = await this.canvas.convertToBlob()\n    //   // const bitmap = await self.createImageBitmap(blob)\n    //   this.mCache.setFrame(frame, bitmap)\n    //   // console.log('[transferToImageBitmap]', bitmap)\n    // } else if (this.canvas instanceof HTMLCanvasElement) {\n    if (this.op.useBitmap && self.createImageBitmap) {\n      self.createImageBitmap(this.canvas).then(bitmap => {\n        this.mCache.setFrame(frame, bitmap)\n      })\n    } else if ('toDataURL' in this.canvas) {\n      const ofsImageBase64 = this.canvas.toDataURL()\n      const ofsImage = new Image()\n      ofsImage.src = ofsImageBase64\n      this.mCache.setFrame(frame, ofsImage)\n    }\n    // old version 保留观察是否有改观\n    /*\n      this.canvas.toBlob(blob => {\n        if (!blob) return\n        if (this.op.useBitmap && self.createImageBitmap) {\n          self.createImageBitmap(blob).then(bitmap => {\n            this.mCache.setFrame(frame, bitmap)\n          })\n        } else {\n          const ofsImage = new Image()\n          ofsImage.src = URL.createObjectURL(blob)\n          // 增加 onload 事件 解决第一次加载会闪屏的问题\n          ofsImage.onload = () => {\n            this.mCache.setFrame(frame, ofsImage)\n          }\n        }\n      })\n\t\t\t*/\n    // }\n  }\n}\nexport default RenderCache\n","import {logger} from 'src/helper/logger'\nimport {isAndroid, isIOS} from 'src/helper/polyfill'\nimport {getTextByMaxWidth, isDataUrl, isOffscreenCanvasSupported} from 'src/helper/utils'\nimport {\n  EScaleMode,\n  type MixEvideoOptions,\n  type VideoAnimateEffectType,\n  type VideoAnimateType,\n  type VideoDataType,\n} from 'src/type/mix'\n\ntype ContextType = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D\nexport default class VideoEntity {\n  public op: MixEvideoOptions\n  public fps = 30\n  public videoFps = 30\n  public config?: VideoAnimateType\n  public isUseMeta = false\n  // public hasAudio = false\n  //\n  private ofs: HTMLCanvasElement | OffscreenCanvas\n  private ctx: CanvasRenderingContext2D | null | OffscreenCanvasRenderingContext2D\n  //\n  private effectTypes = {\n    txt: ['txt', 'text'],\n    img: ['img', 'image'],\n  }\n  // data keys\n  public effectWidth = 'effectWidth'\n  public effectHeight = 'effectHeight'\n  public effectTag = 'effectTag'\n  public effectType = 'effectType'\n  public effectId = 'effectId'\n  public renderFrame = 'renderFrame'\n  public outputFrame = 'outputFrame'\n  public frameIndex = 'frameIndex'\n  public scaleMode = 'scaleMode'\n  public data = 'data'\n  //\n  constructor(op: MixEvideoOptions) {\n    this.op = op\n    const canvas = isOffscreenCanvasSupported() ? new OffscreenCanvas(300, 300) : document.createElement('canvas')\n    const ctx = canvas.getContext('2d', {willReadFrequently: true}) // willReadFrequently 表示是否计划有大量的回读操作，频繁调用getImageData()方法时能节省内存\n    // canvas.style.display = 'none'\n    // document.body.appendChild(canvas)\n    this.ctx = ctx as any\n    this.ofs = canvas\n    if (op.useMetaData) {\n      this.isUseMeta = true\n    }\n    /**\n     * polyfill map\n     */\n    if (op.dataUrl) {\n      this.effectHeight = 'h'\n      this.effectWidth = 'w'\n      this.effectTag = 'srcTag'\n      this.effectType = 'srcType'\n      this.effectId = 'srcId'\n      this.renderFrame = 'frame'\n      this.outputFrame = 'mFrame'\n      this.frameIndex = 'i'\n      this.data = 'obj'\n    }\n  }\n\n  destroy() {\n    if (this.ofs) {\n      this.ctx = null\n      if (this.ofs instanceof HTMLCanvasElement) this.ofs.remove()\n      else this.ofs = undefined\n    }\n    this.config = undefined\n  }\n  /**\n   * yy视频设置\n   * @param config\n   */\n  setConfig(config: VideoAnimateType) {\n    // this.config = data\n    this.config = config\n    if (config.descript.fps) {\n      this.fps = config.descript.fps\n      this.videoFps = config.descript.fps\n    }\n    // if (config.descript.hasAudio) {\n    //   this.hasAudio = true\n    // }\n  }\n  async setup() {\n    if (this.op.dataUrl) {\n      const {info, src, frame}: any = await this.getConfig(this.op.dataUrl)\n      this.fps = info.fps || this.fps\n      if (info.fps) {\n        this.videoFps = info.fps\n      }\n      // console.log('info.fps', info.fps, 'this.fps', this.fps)\n      this.config = {\n        descript: {\n          width: info.videoW,\n          height: info.videoH,\n          isEffect: info.isVapx,\n          rgbFrame: info.rgbFrame,\n          alphaFrame: info.aFrame,\n          fps: info.fps,\n          version: 0,\n        },\n        effect: src,\n        datas: frame,\n      }\n    }\n    if (this.op.fps) {\n      this.fps = this.op.fps\n    } else {\n      this.op.fps = this.fps\n    }\n    // *** requestAnimationFrame 需要降帧防止抖动\n    // console.log('this.fps', this.fps)\n    await this.parseFromSrcAndOptions()\n  }\n  private get isUseBitmap() {\n    return !!self.createImageBitmap && this.op.useBitmap\n  }\n  //\n  private dataURItoBlob(dataURI: string) {\n    const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] // mime类型\n    const byteString = self.atob(dataURI.split(',')[1]) //base64 解码\n    const arrayBuffer = new ArrayBuffer(byteString.length) //创建缓冲数组\n    const intArray = new Uint8Array(arrayBuffer) //创建视图\n\n    for (let i = 0; i < byteString.length; i++) {\n      intArray[i] = byteString.charCodeAt(i)\n    }\n    return new Blob([intArray], {type: mimeString})\n  }\n  /* private fileToDataUrl(file: HTMLInputElement): Promise<string | undefined> {\n    return new Promise((resolve, reject) => {\n      const reader = new FileReader()\n      reader.readAsDataURL(file.files[0])\n      reader.onloadend = () => resolve(reader.result as string)\n      reader.onerror = e => reject(undefined)\n    })\n  } */\n  /* private fileToBlob(file: HTMLInputElement): Promise<Blob | undefined> {\n    return new Promise((resolve, reject) => {\n      const reader = new FileReader()\n      reader.readAsArrayBuffer(file.files[0])\n      reader.onloadend = () => {\n        const blob = new Blob([new Uint8Array(reader.result as ArrayBuffer)], {type: file.type})\n        resolve(blob)\n      }\n      reader.onerror = e => reject(undefined)\n    })\n  } */\n  private createImageElement(url): Promise<HTMLImageElement | undefined> {\n    return new Promise((resolve, reject) => {\n      const img = new Image()\n      img.crossOrigin = 'anonymous'\n      img.onload = () => {\n        resolve(img)\n      }\n      img.onerror = e => {\n        logger.error('frame load fail:' + url)\n        // reject(new Error('frame load fail:' + url))\n        reject(undefined)\n      }\n      img.src = url\n    })\n  }\n  /**\n   * loadImg\n   * @param url 支持 HTTP DATAURL\n   * @returns\n   */\n  private async loadImg(url: string): Promise<HTMLImageElement | ImageBitmap | undefined> {\n    try {\n      const isBase64 = isDataUrl(url)\n      if (this.isUseBitmap) {\n        let blob\n        // 取消 HTMLInputElement 对象\n        // if (url instanceof HTMLInputElement) {\n        //   blob = await this.fileToBlob(url)\n        // } else {\n        if (isBase64) {\n          blob = this.dataURItoBlob(url)\n          // base 64 不需要执行 imageOrientation: 'flipY'\n          // return self.createImageBitmap(blob)\n        } else {\n          blob = await fetch(url)\n            .then(r => {\n              if (r.ok) {\n                return r.blob()\n              } else {\n                logger.error('fetch request failed, url: ' + url)\n                return undefined\n              }\n            })\n            .catch(err => {\n              logger.error('fetch, err=', err)\n              return undefined\n            })\n        }\n        // const img = document.createElement('img')\n        // img.src = URL.createObjectURL(blob)\n        // document.body.appendChild(img)\n        // console.log(blob)\n        // }\n        // 适配 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1) 解决自动翻转的问题\n        if (blob) {\n          //反转 flipY\n          // console.log('this.op.renderType', this.op.renderType)\n          return this.op.renderType === 'canvas2d'\n            ? self.createImageBitmap(blob)\n            : self.createImageBitmap(blob, {imageOrientation: 'flipY'})\n        } else {\n          return undefined\n        }\n      }\n      // if (url instanceof HTMLInputElement) {\n      //   url = await this.fileToDataUrl(url)\n      // } else if (typeof url === 'string' && url.indexOf('http') === -1 && !isBase64) {\n      //   url = `${location.protocol}//${location.host}${url}`\n      // }\n      if (typeof url === 'string' && url.indexOf('http') === -1 && !isBase64) {\n        url = `${location.protocol}//${location.host}${url}`\n      }\n      // url base64 都可以创建 image element\n      return this.createImageElement(url)\n    } catch (e) {\n      logger.warn('fetch, else err=', e)\n      // this.op?.onEnd?.(e)\n      return undefined\n    }\n  }\n\n  public effectTypeById(effectId: any): string {\n    let type = ''\n    const effect = this.config?.effect\n    if (effect) {\n      for (let index = 0; index < effect.length; index++) {\n        const item = effect[index]\n        if (item.effectId == effectId) {\n          type = item.effectType\n          break\n        }\n      }\n    }\n\n    return type\n  }\n\n  public isTextTypeById(effectId: any): boolean {\n    const type = this.effectTypeById(effectId)\n    // logger.debug('isTextTypeById, else effectId=', effectId, ', type=', type)\n    return this.effectTypes.txt.indexOf(type) > -1\n  }\n\n  private parseFromSrcAndOptions() {\n    if (!this.config?.effect) return\n    const effects = this.op.effects || {}\n    // logger.debug('parseFromSrcAndOptions, this.config.effect=', this.config.effect, effects)\n    return Promise.all(\n      this.config.effect.map(async item => {\n        //\n        const effectType = item[this.effectType]\n        const effectTag = item[this.effectTag]\n        // text\n        if (this.effectTypes.txt.indexOf(effectType) > -1) {\n          // if (this.op['fontStyle'] && !item['fontStyle']) {\n          //   item['fontStyle'] = this.op['fontStyle']\n          // }\n          logger.debug('parseFromSrcAndOptions effectTag=', effectTag)\n          let effectOp = effects[effectTag]\n          if (!effectOp && effectTag.indexOf('_') > 0) {\n            // 对于'key7_ffffff_18'格式的key, 外部传入'key7_'也能支持\n            const tags = effectTag.split('_')\n            const tag = tags[0] + '_'\n            effectOp = effects[tag]\n            logger.debug('parseFromSrcAndOptions 2, tag=', tag)\n          }\n          logger.debug('parseFromSrcAndOptions 2, effectTag=', effectTag, effectOp)\n          if (effectOp) {\n            const eOptions = {\n              fontStyle: effects.fontStyle,\n              fontColor: effects.fontColor,\n              fontSize: effects.fontSize,\n            }\n\n            if (typeof effectOp === 'string') {\n              item.text = effectOp\n            } else {\n              item.text = effectOp.text\n\n              const style = effectOp\n              if (style.fontStyle) eOptions.fontStyle = style.fontStyle\n              if (style.fontColor) eOptions.fontColor = style.fontColor\n              if (style.fontSize) eOptions.fontSize = style.fontSize\n            }\n            item.img = await this.makeTextImg(item, eOptions, item.effectHeight)\n          }\n        } // image\n        else if (this.effectTypes.img.indexOf(effectType) > -1) {\n          // console.log(`[effect] effectTag:`, effectTag, ':', effects[effectTag])\n          item.img = await this.makeImage(item, effects[effectTag])\n        }\n      }),\n    )\n  }\n  /**\n   * effect 图片处理\n   * @param item\n   * @param eOptions\n   * @returns\n   */\n  private async makeImage(item: VideoAnimateEffectType, url: string) {\n    // console.log(`[effect] makeImage:`, item, url)\n    if (!this.ctx) return\n    const ctx = this.ctx\n    const w = Math.ceil(item[this.effectWidth])\n    const h = Math.ceil(item[this.effectHeight])\n    let img = null\n    if (url) {\n      img = await this.loadImg(url)\n    }\n    // const isBase64 = isDataUrl(url)\n    ctx.canvas.width = w\n    ctx.canvas.height = h\n    // console.log(`makeImage`, item.scaleMode, w, h, img)\n    if (item.scaleMode && img) {\n      switch (item.scaleMode) {\n        case EScaleMode.aspectFill: {\n          // 最大适配\n          let adapt = 1\n          if (w / h > img.width / img.height) {\n            adapt = w / img.width\n          } else {\n            adapt = h / img.height\n          }\n          const drawWidth = Math.round(img.width * adapt)\n          const drawHeight = Math.round(img.height * adapt)\n          const sx = Math.round((w - drawWidth) / 2)\n          let sy = 0\n          if(this.op.renderType === 'webgpu'){\n             sy = Math.round((h - drawHeight) / 2)\n          }\n          else{\n             sy = Math.round((drawHeight - h) / 2)\n          }\n          // console.log(\n          //   `[effect] before draw: w ,h ,drawWidth, drawHeight, sx, sy, adapt`,\n          //   w,\n          //   h,\n          //   drawWidth,\n          //   drawHeight,\n          //   sx,\n          //   sy,\n          //   adapt,\n          // )\n          ctx.save()\n          if(this.op.renderType === 'webgpu'){\n              ctx.translate(0, 0)\n          }\n          else{\n             ctx.translate(0, drawHeight)\n             ctx.scale(1, -1)\n          }\n          ctx.drawImage(img, sx, sy, drawWidth, drawHeight)\n          ctx.restore()\n          return ctx.getImageData(0, 0, w, h)\n        }\n        case EScaleMode.aspectFit: {\n          // 最小适配\n          let adapt = 1\n          if (w / h < img.width / img.height) {\n            adapt = w / img.width\n          } else {\n            adapt = h / img.height\n          }\n          const drawWidth = Math.round(img.width * adapt)\n          const drawHeight = Math.round(img.height * adapt)\n          const sx = Math.round((w - drawWidth) / 2)\n          let sy = 0\n          if(this.op.renderType === 'webgpu'){\n             sy = Math.round((h - drawHeight) / 2)\n          }\n          else{\n             sy = Math.round((drawHeight - h) / 2)\n          }\n          // console.log(\n          //   `[effect] before draw: w ,h ,drawWidth, drawHeight, sx, sy, adapt`,\n          //   w,\n          //   h,\n          //   drawWidth,\n          //   drawHeight,\n          //   sx,\n          //   sy,\n          //   adapt,\n          // )\n          ctx.save()\n          if(this.op.renderType === 'webgpu'){\n              ctx.translate(0, 0)\n          }\n          else{\n             ctx.translate(0, drawHeight)\n             ctx.scale(1, -1)\n          }\n          ctx.drawImage(img, sx, sy, drawWidth, drawHeight)\n          ctx.restore()\n          return ctx.getImageData(0, 0, w, h)\n        }\n        case EScaleMode.scaleFill: // 变形适配\n          return img\n        default:\n          return img\n      }\n    } else if (img) {\n      return img\n    } else {\n      // 挖空区域\n      ctx.clearRect(0, 0, w, h)\n      return ctx.getImageData(0, 0, w, h)\n    }\n  }\n\n  _getText(ctx: ContextType, text: string, maxWidth: number): string {\n    if (!this.op?.font?.overflow || this.op.font.overflow === 'cut') {\n      const textWidth = ctx.measureText(text).width\n      if (maxWidth == undefined) {\n        maxWidth = textWidth\n      } else if (textWidth > maxWidth) {\n        let len = text.length\n        while (ctx.measureText(text + '...').width > maxWidth && len > 0) {\n          len = len - 1\n          text = text.substring(0, len)\n        }\n        text = text + '...'\n      }\n    }\n\n    return text\n  }\n\n  private defaultFontInfo(fontSize: number, ctx: ContextType) {\n    // console.log('font=', ctx.font)\n    if (isAndroid) {\n      let familyName = 'sans-serif'\n      const originFont = ctx.font.split(' ')\n      if (originFont && originFont.length) {\n        familyName = originFont[originFont.length - 1]\n      }\n\n      return ['normal', `${Math.round(fontSize)}px`, familyName]\n    } else if (isIOS) {\n      return ['normal', `${Math.round(fontSize)}px`, 'SFUI-Heavy']\n    } else {\n      return ['600', `${Math.round(fontSize)}px`, 'Microsoft YaHei']\n    }\n  }\n\n  /**\n   * 文字转换图片\n   * @param item\n   */\n  private async makeTextImg(item: VideoAnimateEffectType, eOptions: any = {}, width = 0) {\n    if (!this.ctx) return\n    const ctx = this.ctx\n    // console.log(`[makeTextImg] eOptions:`, eOptions)\n    if (eOptions.fontStyle) item.fontStyle = eOptions.fontStyle\n    if (eOptions.fontColor) item.fontColor = eOptions.fontColor\n    if (eOptions.fontSize) item.fontSize = eOptions.fontSize\n    const {fontStyle, fontColor, fontSize} = item\n    //\n    const w = Math.ceil(item[this.effectWidth])\n    const h = Math.ceil(item[this.effectHeight])\n    ctx.canvas.width = w\n    ctx.canvas.height = h\n    ctx.textBaseline = 'middle'\n    ctx.textAlign = 'center'\n    const txt = item.text || ''\n    const txtlength = txt.length\n    const defaultFontSize = h - 2\n    // console.log(\n    //   `[makeTextImg]: fontStyle${fontStyle}, fontColor${fontColor}, fontSize${fontSize}, w${w}, h${h}, txt${txt}, txtlength:${txtlength}`,\n    //   this.op,\n    // )\n\n    const getFontStyle = (fontSize?: number) => {\n      fontSize = fontSize || defaultFontSize\n      if (!this.op?.font?.overflow || this.op.font.overflow === 'cut') {\n        // const maxFontLength = Math.ceil(w / fontSize) - 2\n        // if (txtlength > maxFontLength) {\n        //   txt = txt.substring(0, maxFontLength) + '...'\n        // }\n      } else if (fontSize * txtlength > w - 1) {\n        fontSize = Math.min((w / txtlength) * 1, defaultFontSize)\n      }\n\n      const font = this.defaultFontInfo(fontSize, ctx)\n      // console.log('@@@@font=', font)\n      // const font = ['600', `${Math.round(fontSize)}px`, 'Microsoft YaHei']\n      if (fontStyle === 'b') {\n        font.unshift('bold')\n      }\n      return font.join(' ')\n    }\n    if (!fontStyle) {\n      const fontStyle = getFontStyle(fontSize)\n      ctx.font = fontStyle\n      if (fontColor) ctx.fillStyle = fontColor\n    } else if (typeof fontStyle == 'string') {\n      ctx.font = fontStyle\n      if (fontColor) ctx.fillStyle = fontColor\n    } else if (typeof fontStyle == 'object') {\n      ctx.font = fontStyle['font'] || getFontStyle(fontSize)\n      ctx.fillStyle = fontStyle['color'] || fontColor\n    } else if (typeof fontStyle == 'function') {\n      ctx.font = getFontStyle(fontSize)\n      if (fontColor) ctx.fillStyle = fontColor\n      fontStyle(null, ctx, item)\n    }\n    logger.debug('getFontStyle, style: ', ctx.font, ', text:', txt)\n    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)\n    const posx = Math.floor(w / 2)\n    let posy = Math.floor(h / 2)\n    if (!isAndroid && !isIOS) {\n      const metrics = ctx.measureText(txt)\n      posy = posy + (metrics.actualBoundingBoxAscent - metrics.actualBoundingBoxDescent) / 2\n    }\n    ctx.fillText(getTextByMaxWidth(txt, ctx.font, w), posx, posy)\n    if (isOffscreenCanvasSupported() && this.ofs instanceof OffscreenCanvas) {\n      const blob = await this.ofs.convertToBlob()\n      const bitmap =\n        this.op.renderType === 'canvas2d'\n          ? self.createImageBitmap(blob)\n          : self.createImageBitmap(blob, {imageOrientation: 'flipY'})\n      return bitmap\n    }\n    return ctx.getImageData(0, 0, w, h)\n  }\n  getFrame(frame: number) {\n    return (\n      this.config.datas &&\n      this.config.datas.find(item => {\n        return item[this.frameIndex] === frame\n      })\n    )\n  }\n  private getConfig(jsonUrl: string): Promise<VideoDataType> {\n    return new Promise((resolve, reject) => {\n      const xhr = new XMLHttpRequest()\n      xhr.open('GET', jsonUrl, true)\n      xhr.responseType = 'json'\n      xhr.onload = () => {\n        if (xhr.status === 200 || (xhr.status === 304 && xhr.response)) {\n          const res = xhr.response\n          resolve(res)\n        } else {\n          reject(new Error('http response invalid' + xhr.status))\n        }\n      }\n      xhr.send()\n    })\n  }\n}\n"],"mappings":"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"}