• 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 { Constants } from '../../common/model/common/Constants';
17import { PhotoEditCrop } from './crop/PhotoEditCrop';
18import { PhotoEditBase } from './base/PhotoEditBase';
19import { PhotoEditMode } from './base/PhotoEditType';
20import { PixelMapWrapper } from './base/PixelMapWrapper';
21import { ImageFilterStack } from './ImageFilterStack';
22import { MediaDataItem } from '@ohos/base/src/main/ets/data/MediaDataItem';
23import { Loader } from './Loader';
24import { Save } from './Save';
25import { Log } from '@ohos/base/src/main/ets/utils/Log';
26
27export class PhotoEditorManager {
28    private TAG: string = 'PhotoEditorManager';
29    private currentMode: PhotoEditMode = PhotoEditMode.EDIT_MODE_MAIN;
30    private origin: PixelMapWrapper = undefined;
31    private item: MediaDataItem = undefined;
32    private editors: Array<PhotoEditBase> = undefined;
33    private historyManager: ImageFilterStack = undefined;
34    isSaving: boolean = false;
35
36    private constructor() {
37        this.historyManager = new ImageFilterStack();
38        this.editors = [];
39        this.editors[PhotoEditMode.EDIT_MODE_CROP] = new PhotoEditCrop();
40    }
41
42    static getInstance(): PhotoEditorManager {
43        if (AppStorage.Get(Constants.PHOTO_EDITOR_MANAGER) == null) {
44            AppStorage.SetOrCreate(Constants.PHOTO_EDITOR_MANAGER, new PhotoEditorManager());
45        }
46        return AppStorage.Get(Constants.PHOTO_EDITOR_MANAGER);
47    }
48
49    initialize(item: MediaDataItem, mode: PhotoEditMode, errCallback?: any) {
50        Log.info(this.TAG, `initialize mode[${mode}]`);
51        this.item = item;
52        Loader.loadPixelMapWrapper(item, true).then((pixelMap) => {
53            if (pixelMap) {
54                this.origin = pixelMap;
55                this.historyManager.setOriginPixelMap(this.origin);
56                this.switchMode(mode);
57            } else {
58                Log.error(this.TAG, 'initialize loadPixelMapWrapper failed');
59                errCallback && errCallback();
60            }
61        })
62    }
63
64    clear() {
65        Log.debug(this.TAG, 'clear');
66        this.editors[this.currentMode] && this.editors[this.currentMode].exit();
67        this.item = undefined;
68        this.origin && this.origin.release();
69        this.origin = undefined;
70        this.historyManager.setOriginPixelMap(undefined);
71        this.historyManager.releaseAll();
72        this.currentMode = PhotoEditMode.EDIT_MODE_MAIN;
73    }
74
75    getPhotoEditBaseInstance(mode: PhotoEditMode): PhotoEditBase {
76        return this.editors[mode];
77    }
78
79    getLastPixelMap(): PixelMapWrapper {
80        let position = this.historyManager.getPosition();
81        Log.debug(this.TAG, `getLastPixelMap position = ${position}`);
82        if (position < 0) {
83            return this.origin;
84        } else {
85            return this.historyManager.at(position).getCache();
86        }
87    }
88
89    switchMode(mode: PhotoEditMode): PhotoEditMode {
90        Log.info(this.TAG, `switchMode: currentMode[${this.currentMode}] mode[${mode}]`);
91        if (this.currentMode == mode) {
92            return mode;
93        }
94
95        // exit current edit mode
96        if (this.editors[this.currentMode] != undefined) {
97            const filter = this.editors[this.currentMode].exit();
98            if (filter != undefined) {
99                // save cache
100                if (!filter.isCached()) {
101                    const prePixelMap = this.getLastPixelMap();
102                    filter.setCache(filter.render(prePixelMap));
103                }
104                this.historyManager.push(filter);
105            }
106        }
107
108        // entry next edit mode
109        let input = this.getLastPixelMap();
110        if (input && this.editors[mode] != undefined) {
111            this.editors[mode].entry(input);
112            // update current edit mode
113            this.currentMode = mode;
114        }
115        return this.currentMode;
116    }
117
118    isRedoValid(): boolean {
119        return this.historyManager.isRedoValid();
120    }
121
122    isUndoValid(): boolean {
123        return this.historyManager.isUndoValid();
124    }
125
126    redo(): boolean {
127        if (this.isRedoValid()) {
128            let newPixel = this.historyManager.doRedo();
129            this.editors[this.currentMode].entry(newPixel);
130            return true;
131        }
132
133        return false;
134    }
135
136    undo(): boolean {
137        if (this.isUndoValid()) {
138            let newPixel = this.historyManager.doUndo();
139            this.editors[this.currentMode].entry(newPixel);
140            return true;
141        }
142
143        return false;
144    }
145
146    async save(isReplace: boolean): Promise<number> {
147        Log.info(this.TAG, `save enter isReplace = ${isReplace}`);
148        this.isSaving = true;
149        const filter = this.editors[this.currentMode].exit();
150        if (filter != undefined) {
151            this.historyManager.push(filter);
152        }
153        return await Save.save(this.item, this.historyManager, isReplace);;
154    }
155}