• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { EditStack } from './utils/EditStack';
17import { ImageFilterBase } from './base/ImageFilterBase';
18import { PixelMapWrapper } from './base/PixelMapWrapper';
19
20enum CacheDirection {
21  BACKWARD,
22  FORWARD
23}
24
25export class ImageFilterStack extends EditStack<ImageFilterBase> {
26  private static readonly CACHE_MAX: number = 20;
27  private cacheStart: number = 0;
28  private cacheEnd: number = 0;
29  private origin: PixelMapWrapper = undefined;
30
31  apply(pixelMap: PixelMapWrapper): PixelMapWrapper {
32    super.forEach((filter: ImageFilterBase) => {
33      pixelMap = filter.render(pixelMap);
34    });
35    return pixelMap;
36  }
37
38  push(filter: ImageFilterBase) {
39    super.push(filter);
40    this.updateCache(CacheDirection.FORWARD);
41  }
42
43  releaseAll() {
44    super.forEach((filter: ImageFilterBase) => {
45      filter && filter.release();
46    }, super.getLength());
47    super.reset();
48    this.cacheStart = 0;
49    this.cacheEnd = 0;
50  }
51
52  setOriginPixelMap(origin: PixelMapWrapper) {
53    this.origin = origin;
54  }
55
56  doRedo(): PixelMapWrapper {
57    let position: number = super.redo();
58    this.updateCache(CacheDirection.FORWARD);
59    return super.at(position).getCache();
60  }
61
62  doUndo(): PixelMapWrapper {
63    let position: number = super.undo();
64    this.updateCache(CacheDirection.BACKWARD);
65    return super.at(position).getCache();
66  }
67
68  private shouldReleaseCache(): boolean {
69    return (this.cacheEnd - this.cacheStart >= ImageFilterStack.CACHE_MAX);
70  }
71
72  private updateCache(direction: CacheDirection) {
73    let position = super.getPosition();
74    let filter = super.at(position);
75    if (direction == CacheDirection.BACKWARD) {
76      if (!filter.isCached()) {
77        let pixelMap = this.origin;
78        filter.setCache(this.apply(pixelMap));
79        this.cacheStart--;
80      }
81
82      if (this.shouldReleaseCache()) {
83        super.at(this.cacheEnd).release();
84        this.cacheEnd--;
85      }
86    } else if (direction == CacheDirection.FORWARD) {
87      if (!filter.isCached()) {
88        let pixelMap = (position > 0) ? super.at(position - 1).getCache() : this.origin;
89        filter.setCache(filter.render(pixelMap));
90        this.cacheEnd++;
91      }
92
93      if (this.shouldReleaseCache()) {
94        super.at(this.cacheStart).release();
95        this.cacheStart++;
96      }
97    }
98  }
99}