⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qpaintengine_d3d.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    STDMETHOD(SetFVF)(DWORD FVF);    STDMETHOD(SetVertexShader)(LPDIRECT3DVERTEXSHADER9 pShader);    STDMETHOD(SetVertexShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount);    STDMETHOD(SetVertexShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount);    STDMETHOD(SetVertexShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount);    STDMETHOD(SetPixelShader)(LPDIRECT3DPIXELSHADER9 pShader);    STDMETHOD(SetPixelShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount);    STDMETHOD(SetPixelShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount);    STDMETHOD(SetPixelShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount);private:    LPDIRECT3DVERTEXSHADER9 m_vertexshader;    LPDIRECT3DPIXELSHADER9 m_pixelshader;    LPDIRECT3DBASETEXTURE9 m_textures[D3D_STAGE_COUNT];    DWORD m_texturestates[D3D_STAGE_COUNT][D3D_TEXTURE_STATES];    DWORD m_samplerstates[D3D_STAGE_COUNT][D3D_SAMPLE_STATES];    DWORD m_renderstate[D3D_RENDER_STATES];    qreal m_radgradfd;    bool m_cosmetic_pen;    int m_pass;    int m_maskchannel;    int m_brushmode;    LPDIRECT3DBASETEXTURE9 m_texture;    D3DXMATRIX m_projection;    D3DXMATRIX m_d3dIdentityMatrix;    bool m_isIdentity;    QTransform m_transformation;    LPDIRECT3DDEVICE9 m_pDevice;    ID3DXEffect *m_effect;    LONG m_refs;    bool m_changed;    qreal m_xoffset, m_yoffset;    static int m_mask_channels[4][4];};//// font cache stuff//struct QD3DGlyphCoord {    // stores the offset and size of a glyph texture    qreal x;    qreal y;    qreal width;    qreal height;    qreal log_width;    qreal log_height;    QFixed x_offset;    QFixed y_offset;};struct QD3DFontTexture {    int x_offset; // current glyph offset within the texture    int y_offset;    int width;    int height;    IDirect3DTexture9 *texture;};typedef QHash<glyph_t, QD3DGlyphCoord*>  QD3DGlyphHash;typedef QHash<QFontEngine*, QD3DGlyphHash*> QD3DFontGlyphHash;typedef QHash<quint64, QD3DFontTexture*> QD3DFontTexHash;class QD3DGlyphCache : public QObject{    Q_OBJECTpublic:    QD3DGlyphCache()        : QObject(0)        , current_cache(0) {}    ~QD3DGlyphCache();    QD3DGlyphCoord *lookup(QFontEngine *, glyph_t);    void cacheGlyphs(QDirect3DPaintEngine *, const QTextItemInt &, const QVarLengthArray<glyph_t> &,                     bool);    void cleanCache();    inline QD3DFontTexture *fontTexture(QFontEngine *engine) {        return font_textures.constFind(reinterpret_cast<quint64>(engine)).value();    }public slots:    void fontEngineDestroyed(QObject *);private:    QImage clearTypeGlyph(QFontEngine *, glyph_t glyph);    QD3DGlyphHash *current_cache;    QD3DFontTexHash font_textures;    QD3DFontGlyphHash font_cache;};QD3DGlyphCache::~QD3DGlyphCache(){}QD3DGlyphCoord *QD3DGlyphCache::lookup(QFontEngine *, glyph_t g){    Q_ASSERT(current_cache != 0);    QD3DGlyphHash::const_iterator it = current_cache->constFind(g);    if (it == current_cache->constEnd())        return 0;    return it.value();}void QD3DGlyphCache::cleanCache(){    QList<quint64> keys = font_textures.keys();    for (int i=0; i<keys.size(); ++i)        font_textures.value(keys.at(i))->texture->Release();    qDeleteAll(font_textures);    qDeleteAll(font_cache);    font_textures.clear();    font_cache.clear();    current_cache = 0;}void QD3DGlyphCache::fontEngineDestroyed(QObject *object){//     qDebug() << "=> font engine destroyed: " << object;    QFontEngine *engine = static_cast<QFontEngine *>(object);    QD3DFontGlyphHash::iterator cache_it = font_cache.find(engine);    if (cache_it != font_cache.end()) {        QD3DGlyphHash *cache = font_cache.take(engine);        delete cache;    }    quint64 font_key = reinterpret_cast<quint64>(engine);    QD3DFontTexture *tex = font_textures.take(font_key);    if (tex) {        tex->texture->Release();        delete tex;    }}QImage QD3DGlyphCache::clearTypeGlyph(QFontEngine *engine, glyph_t glyph){    glyph_metrics_t gm = engine->boundingBox(glyph);    int glyph_x = qFloor(gm.x.toReal());    int glyph_y = qFloor(gm.y.toReal());    int glyph_width = qCeil((gm.x + gm.width).toReal()) -  glyph_x + 2;    int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y + 2;    if (glyph_width + glyph_x <= 0 || glyph_height <= 0)        return QImage();    QImage im(glyph_width + glyph_x, glyph_height, QImage::Format_ARGB32_Premultiplied);    im.fill(0xff000000); // solid black    QPainter p(&im);    p.setPen(Qt::white);    p.setBrush(Qt::NoBrush);    QTextItemInt ti;    ti.ascent = engine->ascent();    ti.descent = engine->descent();    ti.width = glyph_width;    ti.fontEngine = engine;    ti.num_glyphs = 1;    QGlyphLayout glyphLayout;    ti.glyphs = &glyphLayout;    glyphLayout.glyph = glyph;    memset(&glyphLayout.attributes, 0, sizeof(glyphLayout.attributes));    glyphLayout.advance.x = glyph_width;    p.drawTextItem(QPointF(-glyph_x, -glyph_y), ti);    p.end();    return im;}#if 0static void dump_font_texture(QD3DFontTexture *tex){    QColor color(Qt::red);    D3DLOCKED_RECT rect;    if (FAILED(tex->texture->LockRect(0, &rect, 0, 0))) {        qDebug() << "debug: unable to lock texture rect.";        return;    }// cleartype version//     uint *tex_data = (uint *) rect.pBits;//     QImage im(tex->width, tex->height, QImage::Format_ARGB32);//     for (int y=0; y<tex->height; ++y) {//         for (int x=0; x<tex->width; ++x) {//             im.setPixel(x, y, ((*(tex_data+x+y*tex->width))));//         }//     }    uchar *tex_data = (uchar *) rect.pBits;    QImage im(rect.Pitch, tex->height, QImage::Format_ARGB32);    for (int y=0; y<tex->height; ++y) {        for (int x=0; x<rect.Pitch; ++x) {            uchar val = ((*(tex_data+x+y*rect.Pitch)));            im.setPixel(x, y, 0xff000000 | (val << 16) | (val << 8) | val);        }    }    tex->texture->UnlockRect(0);    static  int i= 0;    im.save(QString("tx%1.png").arg(i++));}#endifvoid QD3DGlyphCache::cacheGlyphs(QDirect3DPaintEngine *engine, const QTextItemInt &ti,                                 const QVarLengthArray<glyph_t> &glyphs, bool clearType){    IDirect3DDevice9 *device = engine->d_func()->m_d3d_device;    QD3DFontGlyphHash::const_iterator cache_it = font_cache.constFind(ti.fontEngine);    QD3DGlyphHash *cache = 0;    if (cache_it == font_cache.constEnd()) {        cache = new QD3DGlyphHash;        font_cache.insert(ti.fontEngine, cache);        connect(ti.fontEngine, SIGNAL(destroyed(QObject *)), SLOT(fontEngineDestroyed(QObject *)));    } else {        cache = cache_it.value();    }    current_cache = cache;    D3DFORMAT tex_format = clearType ? D3DFMT_A8R8G8B8 : D3DFMT_A8;    quint64 font_key = reinterpret_cast<quint64>(ti.fontEngine);    QD3DFontTexHash::const_iterator it = font_textures.constFind(font_key);    QD3DFontTexture *font_tex = 0;    if (it == font_textures.constEnd()) {        // alloc a new texture, put it into the cache        int tex_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5;        int tex_width = tex_height * 30; // ###        IDirect3DTexture9 *tex;        if (FAILED(device->CreateTexture(tex_width, tex_height, 1, 0,                                         tex_format, D3DPOOL_MANAGED, &tex, NULL)))        {            qWarning("QD3DGlyphCache::cacheGlyphs(): can't allocate font texture (%dx%d).",                     tex_width, tex_height);            return;        } else {//             qDebug() << "=> new font texture: " << QSize(tex_width,tex_height);            font_tex = new QD3DFontTexture;            font_tex->texture = tex;            font_tex->x_offset = 0;            font_tex->y_offset = 0;            font_tex->width = tex_width;            font_tex->height = tex_height;            font_textures.insert(font_key, font_tex);        }    } else {        font_tex = it.value();        // make it current render target..    }    // cache each glyph    for (int i=0; i<glyphs.size(); ++i) {        QD3DGlyphHash::const_iterator it = cache->constFind(glyphs[i]);        if (it == cache->constEnd()) {            glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]);            int glyph_width = qCeil(metrics.width.toReal()) + 5;            int glyph_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5;            if (font_tex->x_offset + glyph_width > font_tex->width) {                // no room on the current line, start new glyph strip                int strip_height = glyph_height;                font_tex->x_offset = 0;                font_tex->y_offset += strip_height;                if (font_tex->y_offset >= font_tex->height) {                    // if no room in the current texture - realloc a larger texture                    int old_tex_height = font_tex->height;                    font_tex->height += strip_height;                    IDirect3DTexture9 *new_tex;                    if (FAILED(device->CreateTexture(font_tex->width, font_tex->height, 1, 0,                                                     tex_format, D3DPOOL_MANAGED, &new_tex, NULL)))                    {                        qWarning("QD3DGlyphCache(): can't re-allocate font texture.");                        return;                    } else {//                         qDebug() << " -> new glyph strip added:" << QSize(font_tex->width,font_tex->height);                        D3DLOCKED_RECT new_rect, old_rect;                        if (FAILED(font_tex->texture->LockRect(0, &old_rect, 0, D3DLOCK_READONLY))) {                            qDebug() << "QD3DGlyphCache: unable to lock texture rect.";                            return;                        }                        if (FAILED(new_tex->LockRect(0, &new_rect, 0, 0))) {                            qDebug() << "QD3DGlyphCache: unable to lock texture rect.";                            return;                        }                        memcpy(new_rect.pBits, old_rect.pBits, new_rect.Pitch * old_tex_height);                        font_tex->texture->UnlockRect(0);                        new_tex->UnlockRect(0);                        engine->d_func()->flushBatch();                        font_tex->texture->Release();                        font_tex->texture = new_tex;                    }                    // update the texture coords and the y offset for the existing glyphs in                    // the cache, because of the texture size change                    QD3DGlyphHash::iterator it = cache->begin();                    while (it != cache->end()) {                        it.value()->height = (it.value()->height * old_tex_height) / font_tex->height;                        it.value()->y = (it.value()->y * old_tex_height) / font_tex->height;                        ++it;                    }                }            }            QD3DGlyphCoord *d3d_glyph = new QD3DGlyphCoord;            d3d_glyph->x = qreal(font_tex->x_offset) / font_tex->width;            d3d_glyph->y = qreal(font_tex->y_offset) / font_tex->height;            d3d_glyph->width = qreal(glyph_width) / font_tex->width;            d3d_glyph->height = qreal(glyph_height) / font_tex->height;            d3d_glyph->log_width = d3d_glyph->width * font_tex->width;            d3d_glyph->log_height = d3d_glyph->height * font_tex->height;            d3d_glyph->x_offset = -metrics.x;            d3d_glyph->y_offset = metrics.y;            QImage glyph_im;            if (clearType)                glyph_im = clearTypeGlyph(ti.fontEngine, glyphs[i]);            else                glyph_im = ti.fontEngine->alphaMapForGlyph(glyphs[i]).convertToFormat(QImage::Format_Indexed8);            // write glyph to texture            D3DLOCKED_RECT rect;            RECT glyph_rect = { font_tex->x_offset, font_tex->y_offset,                                font_tex->x_offset + glyph_im.width(),                                font_tex->y_offset + glyph_im.height() };//             qDebug() << "  > new glyph char added:" << QSize(glyph_im.width(), glyph_im.height());            if (FAILED(font_tex->texture->LockRect(0, &rect, &glyph_rect, 0))) {                qDebug() << "QD3DGlyphCache: unable to lock texture rect.";                return;            }            // ### unify these loops            if (clearType) {                int ppl = rect.Pitch / 4;                uint *tex_data = (uint *) rect.pBits;                for (int y=0; y<glyph_im.height(); ++y) {                    uint *s = (uint *) glyph_im.scanLine(y);                    for (int x=0; x<glyph_im.width(); ++x) {                        tex_data[ppl*y + x] = *s;                        ++s;                    }                }            } else {                int ppl = rect.Pitch;                uchar *tex_data = (uchar *) rect.pBits;                for (int y=0; y<glyph_im.height(); ++y) {                    uchar *s = (uchar *) glyph_im.scanLine(y);                    for (int x=0; x<glyph_im.width(); ++x) {                        tex_data[ppl*y + x] = *s;                        ++s;                    }                }            }            font_tex->texture->UnlockRect(0);            // debug//             dump_font_texture(font_tex);            if (font_tex->x_offset + glyph_width > font_tex->width) {                font_tex->x_offset = 0;                font_tex->y_offset += glyph_height;            } else {                font_tex->x_offset += glyph_width;            }            cache->insert(glyphs[i], d3d_glyph);        }    }}Q_GLOBAL_STATIC(QD3DGlyphCache, qd3d_glyph_cache)//// end font caching stuff//////  D3D image cache stuff//// ### keep the GL stuff in mind..typedef void (*_qt_image_cleanup_hook_64)(qint64);extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;static void qd3d_image_cleanup(qint64 key);class QD3DImage{public:    QD3DImage(IDirect3DDevice9 *device, const QImage &image);    ~QD3DImage();    IDirect3DTexture9 *texture;};static QList<IDirect3DTexture9 *> qd3d_release_list;QD3DImage::QD3DImage(IDirect3DDevice9 *device, const QImage &image){    texture = 0;    Q_ASSERT(device);    QImage im = image.convertToFormat(QImage::Format_ARGB32);    if (FAILED(device->CreateTexture(im.width(), im.height(), 1, 0,                                     D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, 0))) {        qWarning("QD3DImage(): unable to create Direct3D texture.");        return;    }//     qDebug(" -> created image texture: %p - 0x%08x%08x",texture,uint (image.cacheKey() >> 32),uint (image.cacheKey() & 0xffffffff));    D3DLOCKED_RECT rect;    if (FAILED(texture->LockRect(0, &rect, 0, 0))) {        qDebug() << "QD3DImage: unable to lock texture rect.";        return;    }    DWORD *dst = (DWORD *) rect.pBits;    DWORD *src = (DWORD *) im.scanLine(0);    Q_ASSERT((rect.Pitch/4) == (im.bytesPerLine()/4));    memcpy(dst, src, rect.Pitch*im.height());    texture->UnlockRect(0);}QD3DImage::~QD3DImage(){    if (texture)        qd3d_release_list.append(texture);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -