1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQuick module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qsgopenvginternalimagenode.h"
41 #include "qsgopenvghelpers.h"
42 
43 #include <VG/openvg.h>
44 
45 QT_BEGIN_NAMESPACE
46 
QSGOpenVGInternalImageNode()47 QSGOpenVGInternalImageNode::QSGOpenVGInternalImageNode()
48 {
49     // Set Dummy material and geometry to avoid asserts
50     setMaterial((QSGMaterial*)1);
51     setGeometry((QSGGeometry*)1);
52 }
53 
~QSGOpenVGInternalImageNode()54 QSGOpenVGInternalImageNode::~QSGOpenVGInternalImageNode()
55 {
56     if (m_subSourceRectImage != 0)
57         vgDestroyImage(m_subSourceRectImage);
58 }
59 
render()60 void QSGOpenVGInternalImageNode::render()
61 {
62     if (!m_texture) {
63         return;
64     }
65 
66     // Set Draw Mode
67     if (opacity() < 1.0) {
68         //Transparent
69         vgSetPaint(opacityPaint(), VG_FILL_PATH);
70         vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
71     } else {
72         vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
73     }
74 
75     // Set Transform
76     vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
77     vgLoadMatrix(transform().constData());
78 
79     VGImage image = static_cast<VGImage>(m_texture->textureId());
80     QSize textureSize = m_texture->textureSize();
81 
82     if (image == VG_INVALID_HANDLE || !textureSize.isValid())
83         return;
84 
85 
86     // If Mirrored
87     if (m_mirror) {
88         vgTranslate(m_targetRect.width(), 0.0f);
89         vgScale(-1.0, 1.0);
90     }
91 
92     if (m_smooth)
93         vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_BETTER);
94     else
95         vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED);
96 
97 
98     if (m_innerTargetRect != m_targetRect) {
99         // border image
100         QSGOpenVGHelpers::qDrawBorderImage(image, textureSize, m_targetRect, m_innerTargetRect, m_subSourceRect);
101     } else if (m_tileHorizontal || m_tileVertical) {
102         // Tilled Image
103 
104         float sx = m_targetRect.width() / (m_subSourceRect.width() * textureSize.width());
105         float sy = m_targetRect.height() / (m_subSourceRect.height() * textureSize.height());
106         QPointF offset(m_subSourceRect.left() * textureSize.width(), m_subSourceRect.top() * textureSize.height());
107 
108         QSGOpenVGHelpers::qDrawTiled(image, textureSize, m_targetRect, offset, sx, sy);
109 
110     } else {
111         // Regular BLIT
112 
113         QRectF sr(m_subSourceRect.left() * textureSize.width(), m_subSourceRect.top() * textureSize.height(),
114                   m_subSourceRect.width() * textureSize.width(), m_subSourceRect.height() * textureSize.height());
115 
116         if (m_subSourceRectImageDirty) {
117             if (m_subSourceRectImage != 0)
118                 vgDestroyImage(m_subSourceRectImage);
119             m_subSourceRectImage = vgChildImage(image, sr.x(), sr.y(), sr.width(), sr.height());
120             m_subSourceRectImageDirty = false;
121         }
122 
123         // If the the source rect is the same as the target rect
124         if (sr == m_targetRect) {
125             vgDrawImage(image);
126         } else {
127             // Scale
128             float scaleX = m_targetRect.width() / sr.width();
129             float scaleY = m_targetRect.height() / sr.height();
130             vgTranslate(m_targetRect.x(), m_targetRect.y());
131             vgScale(scaleX, scaleY);
132             vgDrawImage(m_subSourceRectImage);
133         }
134     }
135 }
136 
setTargetRect(const QRectF & rect)137 void QSGOpenVGInternalImageNode::setTargetRect(const QRectF &rect)
138 {
139     if (rect == m_targetRect)
140         return;
141     m_targetRect = rect;
142     markDirty(DirtyGeometry);
143 }
144 
setInnerTargetRect(const QRectF & rect)145 void QSGOpenVGInternalImageNode::setInnerTargetRect(const QRectF &rect)
146 {
147     if (rect == m_innerTargetRect)
148         return;
149     m_innerTargetRect = rect;
150     markDirty(DirtyGeometry);
151 }
152 
setInnerSourceRect(const QRectF & rect)153 void QSGOpenVGInternalImageNode::setInnerSourceRect(const QRectF &rect)
154 {
155     if (rect == m_innerSourceRect)
156         return;
157     m_innerSourceRect = rect;
158     markDirty(DirtyGeometry);
159 }
160 
setSubSourceRect(const QRectF & rect)161 void QSGOpenVGInternalImageNode::setSubSourceRect(const QRectF &rect)
162 {
163     if (rect == m_subSourceRect)
164         return;
165     m_subSourceRect = rect;
166     m_subSourceRectImageDirty = true;
167     markDirty(DirtyGeometry);
168 }
169 
setTexture(QSGTexture * texture)170 void QSGOpenVGInternalImageNode::setTexture(QSGTexture *texture)
171 {
172     m_texture = texture;
173     m_subSourceRectImageDirty = true;
174     markDirty(DirtyMaterial);
175 }
176 
setMirror(bool mirror)177 void QSGOpenVGInternalImageNode::setMirror(bool mirror)
178 {
179     if (m_mirror != mirror) {
180         m_mirror = mirror;
181         markDirty(DirtyMaterial);
182     }
183 }
184 
setMipmapFiltering(QSGTexture::Filtering)185 void QSGOpenVGInternalImageNode::setMipmapFiltering(QSGTexture::Filtering)
186 {
187 }
188 
setFiltering(QSGTexture::Filtering filtering)189 void QSGOpenVGInternalImageNode::setFiltering(QSGTexture::Filtering filtering)
190 {
191     bool smooth = (filtering == QSGTexture::Linear);
192     if (smooth == m_smooth)
193         return;
194 
195     m_smooth = smooth;
196     markDirty(DirtyMaterial);
197 }
198 
setHorizontalWrapMode(QSGTexture::WrapMode wrapMode)199 void QSGOpenVGInternalImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode)
200 {
201     bool tileHorizontal = (wrapMode == QSGTexture::Repeat);
202     if (tileHorizontal == m_tileHorizontal)
203         return;
204 
205     m_tileHorizontal = tileHorizontal;
206     markDirty(DirtyMaterial);
207 }
208 
setVerticalWrapMode(QSGTexture::WrapMode wrapMode)209 void QSGOpenVGInternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode)
210 {
211     bool tileVertical = (wrapMode == QSGTexture::Repeat);
212     if (tileVertical == m_tileVertical)
213         return;
214 
215     m_tileVertical = (wrapMode == QSGTexture::Repeat);
216     markDirty(DirtyMaterial);
217 }
218 
update()219 void QSGOpenVGInternalImageNode::update()
220 {
221 }
222 
preprocess()223 void QSGOpenVGInternalImageNode::preprocess()
224 {
225     bool doDirty = false;
226     QSGLayer *t = qobject_cast<QSGLayer *>(m_texture);
227     if (t) {
228         doDirty = t->updateTexture();
229         markDirty(DirtyGeometry);
230     }
231     if (doDirty)
232         markDirty(DirtyMaterial);
233 }
234 
235 QT_END_NAMESPACE
236 
237 
238 
239 
240