13b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/*
23b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * Copyright (C) 2013 The Android Open Source Project
33b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy *
43b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
53b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * you may not use this file except in compliance with the License.
63b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * You may obtain a copy of the License at
73b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy *
83b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
93b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy *
103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * Unless required by applicable law or agreed to in writing, software
113b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
123b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * See the License for the specific language governing permissions and
143b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * limitations under the License.
153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy */
163b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
173b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#ifndef ANDROID_HWUI_UV_MAPPER_H
183b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#define ANDROID_HWUI_UV_MAPPER_H
193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
203b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include "Rect.h"
213b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guynamespace android {
233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guynamespace uirenderer {
243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
253b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/**
263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * This class can be used to map UV coordinates from the [0..1]
273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * range to other arbitrary ranges. All the methods below assume
283b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * that the input values lie in the [0..1] range already.
293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy */
303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyclass UvMapper {
313b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guypublic:
323b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Using this constructor is equivalent to not using any mapping at all.
343b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * UV coordinates in the [0..1] range remain in the [0..1] range.
353b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
363b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    UvMapper(): mIdentity(true), mMinU(0.0f), mMaxU(1.0f), mMinV(0.0f), mMaxV(1.0f) {
373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
393b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Creates a new mapper with the specified ranges for U and V coordinates.
413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * The parameter minU must be < maxU and minV must be < maxV.
423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    UvMapper(float minU, float maxU, float minV, float maxV):
443b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        mMinU(minU), mMaxU(maxU), mMinV(minV), mMaxV(maxV) {
453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        checkIdentity();
463b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
473b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
483b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
493b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Returns true if calling the map*() methods has no effect (that is,
503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * texture coordinates remain in the 0..1 range.)
513b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
523b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    bool isIdentity() const {
533b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        return mIdentity;
543b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
553b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
573b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Changes the U and V mapping ranges.
583b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * The parameter minU must be < maxU and minV must be < maxV.
593b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
603b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    void setMapping(float minU, float maxU, float minV, float maxV) {
613b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        mMinU = minU;
623b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        mMaxU = maxU;
633b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        mMinV = minV;
643b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        mMaxV = maxV;
653b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        checkIdentity();
663b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
673b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
683b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
693b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Maps a single value in the U range.
703b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
713b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    void mapU(float& u) const {
723b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        if (!mIdentity) u = lerp(mMinU, mMaxU, u);
733b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
743b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
753b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
763b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Maps a single value in the V range.
773b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
783b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    void mapV(float& v) const {
793b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        if (!mIdentity) v = lerp(mMinV, mMaxV, v);
803b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
813b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
823b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
833b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Maps the specified rectangle in place. This method assumes:
843b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * - left = min. U
853b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * - top = min. V
863b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * - right = max. U
873b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * - bottom = max. V
883b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
893b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    void map(Rect& texCoords) const {
903b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        if (!mIdentity) {
913b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            texCoords.left = lerp(mMinU, mMaxU, texCoords.left);
923b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            texCoords.right = lerp(mMinU, mMaxU, texCoords.right);
933b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            texCoords.top = lerp(mMinV, mMaxV, texCoords.top);
943b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            texCoords.bottom = lerp(mMinV, mMaxV, texCoords.bottom);
953b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        }
963b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
973b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
983b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
993b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Maps the specified UV coordinates in place.
1003b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
1013b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    void map(float& u1, float& v1, float& u2, float& v2) const {
1023b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        if (!mIdentity) {
1033b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            u1 = lerp(mMinU, mMaxU, u1);
1043b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            u2 = lerp(mMinU, mMaxU, u2);
1053b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            v1 = lerp(mMinV, mMaxV, v1);
1063b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            v2 = lerp(mMinV, mMaxV, v2);
1073b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        }
1083b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
1093b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    void dump() const {
1113b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        ALOGD("mapper[minU=%.2f maxU=%.2f minV=%.2f maxV=%.2f]", mMinU, mMaxU, mMinV, mMaxV);
1123b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
1133b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1143b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyprivate:
1153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    static float lerp(float start, float stop, float amount) {
1163b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        return start + (stop - start) * amount;
1173b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
1183b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    void checkIdentity() {
1203b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        mIdentity = mMinU == 0.0f && mMaxU == 1.0f && mMinV == 0.0f && mMaxV == 1.0f;
1213b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
1223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    bool mIdentity;
1243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    float mMinU;
1253b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    float mMaxU;
1263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    float mMinV;
1273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    float mMaxV;
1283b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy};
1293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; // namespace uirenderer
1313b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; // namespace android
1323b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#endif // ANDROID_HWUI_UV_MAPPER_H
134