diff options
-rw-r--r-- | vcl/inc/opengl/AccumulatedTextures.hxx | 17 | ||||
-rw-r--r-- | vcl/inc/opengl/texture.hxx | 6 | ||||
-rw-r--r-- | vcl/inc/openglgdiimpl.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/win/salgdi.h | 5 | ||||
-rw-r--r-- | vcl/opengl/gdiimpl.cxx | 4 | ||||
-rw-r--r-- | vcl/opengl/texture.cxx | 33 | ||||
-rw-r--r-- | vcl/win/gdi/salgdi.cxx | 8 | ||||
-rw-r--r-- | vcl/win/gdi/winlayout.cxx | 384 |
8 files changed, 187 insertions, 272 deletions
diff --git a/vcl/inc/opengl/AccumulatedTextures.hxx b/vcl/inc/opengl/AccumulatedTextures.hxx index 9ce170c2a0af..e74c06535f69 100644 --- a/vcl/inc/opengl/AccumulatedTextures.hxx +++ b/vcl/inc/opengl/AccumulatedTextures.hxx @@ -11,6 +11,8 @@ #ifndef INCLUDED_VCL_INC_OPENGL_ACCUMULATEDTEXTURES_H #define INCLUDED_VCL_INC_OPENGL_ACCUMULATEDTEXTURES_H +#include <vcl/opengl/OpenGLHelper.hxx> + #include <o3tl/make_unique.hxx> #include "opengl/texture.hxx" #include <memory> @@ -34,10 +36,10 @@ struct AccumulatedTexturesEntry : maTexture(rTexture) {} - void insert(const SalColor& aColor, const SalTwoRect& r2Rect) + void insert(const OpenGLTexture& rTexture, const SalColor& aColor, const SalTwoRect& r2Rect) { TextureDrawParameters& aDrawParameters = maColorTextureDrawParametersMap[aColor]; - maTexture.FillCoords<GL_TRIANGLES>(aDrawParameters.maTextureCoords, r2Rect, false); + rTexture.FillCoords<GL_TRIANGLES>(aDrawParameters.maTextureCoords, r2Rect, false); GLfloat nX1 = r2Rect.mnDestX; GLfloat nY1 = r2Rect.mnDestY; @@ -86,19 +88,18 @@ public: maEntries.clear(); } - void insert(const OpenGLTexture& rTexture, const SalColor& aColor, const SalTwoRect& r2Rect) + void insert(OpenGLTexture& rTexture, const SalColor& aColor, const SalTwoRect& r2Rect) { GLuint nTextureId = rTexture.Id(); - auto iterator = maEntries.find(nTextureId); - - if (iterator == maEntries.end()) + if (maEntries.find(nTextureId) == maEntries.end()) { - maEntries[nTextureId] = o3tl::make_unique<AccumulatedTexturesEntry>(rTexture); + OpenGLTexture aWholeTexture(rTexture.GetWholeTexture()); + maEntries[nTextureId] = o3tl::make_unique<AccumulatedTexturesEntry>(aWholeTexture); } std::unique_ptr<AccumulatedTexturesEntry>& rEntry = maEntries[nTextureId]; - rEntry->insert(aColor, r2Rect); + rEntry->insert(rTexture, aColor, r2Rect); } AccumulatedTexturesMap& getAccumulatedTexturesMap() diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx index f48a1a166b03..a220875ba1ac 100644 --- a/vcl/inc/opengl/texture.hxx +++ b/vcl/inc/opengl/texture.hxx @@ -96,7 +96,7 @@ private: public: OpenGLTexture(); - OpenGLTexture(ImplOpenGLTexture* pImpl, Rectangle aRectangle, int nSlotNumber = 0); + OpenGLTexture(ImplOpenGLTexture* pImpl, Rectangle aRectangle, int nSlotNumber); OpenGLTexture( int nWidth, int nHeight, bool bAllocate = true ); OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, void const * pData ); @@ -113,13 +113,15 @@ public: void GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted=false ) const; void GetWholeCoord( GLfloat* pCoord ) const; - + OpenGLTexture GetWholeTexture(); void Bind(); void Unbind(); void Read( GLenum nFormat, GLenum nType, sal_uInt8* pData ); GLuint AddStencil(); GLuint StencilId() const; + bool CopyData(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData); + void SaveToFile(const OUString& rFileName); GLenum GetFilter() const; diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index 0fb2941ace9c..756190135daa 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -147,7 +147,7 @@ public: void DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ); void DrawAxialGradient( const Gradient& rGradient, const Rectangle& rRect ); void DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect ); - void DeferredTextDraw(const OpenGLTexture& rTexture, const SalColor nMaskColor, const SalTwoRect& rPosAry); + void DeferredTextDraw(OpenGLTexture& rTexture, const SalColor nMaskColor, const SalTwoRect& rPosAry); void FlushDeferredDrawing(bool bInDraw = false); public: diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index ffd83ab251ad..8866dcfbc289 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -172,11 +172,16 @@ public: SalTwoRect getTwoRect() { return maRects; } + Size getBitmapSize() { return Size(maRects.mnSrcWidth, maRects.mnSrcHeight); } + /// Reset the DC with the defined color. void fill(sal_uInt32 color); /// Obtain the texture; the caller must delete it after use. OpenGLTexture* getTexture(); + + /// Copy bitmap data to the texture. Texutre must be initialized and the correct size to hold the bitmap. + bool copyToTexture(OpenGLTexture& aTexture); }; class WinSalGraphics : public SalGraphics diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index bfa48b48402a..bf979d0cba10 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -1669,7 +1669,7 @@ void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, SalColor nMaskColor, mpProgram->Clean(); } -void OpenGLSalGraphicsImpl::DeferredTextDraw(const OpenGLTexture& rTexture, SalColor aMaskColor, const SalTwoRect& rPosAry) +void OpenGLSalGraphicsImpl::DeferredTextDraw(OpenGLTexture& rTexture, SalColor aMaskColor, const SalTwoRect& rPosAry) { mpAccumulatedTextures->insert(rTexture, aMaskColor, rPosAry); } @@ -1682,6 +1682,8 @@ void OpenGLSalGraphicsImpl::FlushDeferredDrawing(bool bIsInDraw) if (!bIsInDraw) PreDraw(); + VCL_GL_INFO("FlushDeferredDrawing"); + OpenGLZone aZone; #if 0 // Draw a background rect under text for debugging - same color shows text from the same texture diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx index fd6d11f04a5a..b9b12adf7c43 100644 --- a/vcl/opengl/texture.cxx +++ b/vcl/opengl/texture.cxx @@ -373,26 +373,31 @@ template <> void OpenGLTexture::FillCoords<GL_TRIANGLES>(std::vector<GLfloat>& aCoord, const SalTwoRect& rPosAry, bool bInverted) const { VCL_GL_INFO("Add coord " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() ); + VCL_GL_INFO(" With 2Rect Src [" << rPosAry.mnSrcX << ", " << rPosAry.mnSrcY << "] wh (" << rPosAry.mnSrcWidth << ", " << rPosAry.mnSrcHeight << ")"); + VCL_GL_INFO(" With 2Rect Dest [" << rPosAry.mnDestX << ", " << rPosAry.mnDestY << "] wh (" << rPosAry.mnDestWidth << ", " << rPosAry.mnDestHeight << ")"); GLfloat x1 = 0.0f; GLfloat x2 = 0.0f; GLfloat y1 = 0.0f; GLfloat y2 = 0.0f; + double fTextureWidth(mpImpl->mnWidth); + double fTextureHeight(mpImpl->mnHeight); + if (mpImpl) { - x1 = (maRect.Left() + rPosAry.mnSrcX) / (double) mpImpl->mnWidth; - x2 = (maRect.Left() + rPosAry.mnSrcX + rPosAry.mnSrcWidth) / (double) mpImpl->mnWidth; + x1 = (maRect.Left() + rPosAry.mnSrcX) / fTextureWidth; + x2 = (maRect.Left() + rPosAry.mnSrcX + rPosAry.mnSrcWidth) / fTextureWidth; if (bInverted) { - y2 = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / (double) mpImpl->mnHeight; - y1 = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / (double) mpImpl->mnHeight; + y2 = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / fTextureHeight; + y1 = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / fTextureHeight; } else { - y1 = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / (double) mpImpl->mnHeight; - y2 = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / (double) mpImpl->mnHeight; + y1 = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / fTextureHeight; + y2 = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / fTextureHeight; } } @@ -433,6 +438,11 @@ void OpenGLTexture::GetWholeCoord( GLfloat* pCoord ) const } } +OpenGLTexture OpenGLTexture::GetWholeTexture() +{ + return OpenGLTexture(mpImpl, Rectangle(Point(0, 0), Size(mpImpl->mnWidth, mpImpl->mnHeight)), -1); +} + GLenum OpenGLTexture::GetFilter() const { if( mpImpl ) @@ -440,6 +450,17 @@ GLenum OpenGLTexture::GetFilter() const return GL_NEAREST; } +bool OpenGLTexture::CopyData(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData) +{ + if (!pData || mpImpl == nullptr) + return false; + + int nX = maRect.Left(); + int nY = maRect.Top(); + + return mpImpl->InsertBuffer(nX, nY, nWidth, nHeight, nFormat, nType, pData); +} + void OpenGLTexture::SetFilter( GLenum nFilter ) { if( mpImpl ) diff --git a/vcl/win/gdi/salgdi.cxx b/vcl/win/gdi/salgdi.cxx index 531b71a8aaa9..7a27878f0620 100644 --- a/vcl/win/gdi/salgdi.cxx +++ b/vcl/win/gdi/salgdi.cxx @@ -591,6 +591,14 @@ OpenGLTexture* OpenGLCompatibleDC::getTexture() return new OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, reinterpret_cast<sal_uInt8*>(mpData)); } +bool OpenGLCompatibleDC::copyToTexture(OpenGLTexture& aTexture) +{ + if (!mpImpl) + return false; + + return aTexture.CopyData(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, reinterpret_cast<sal_uInt8*>(mpData)); +} + WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hWnd, SalGeometryProvider *pProvider): mhLocalDC(0), mbPrinter(eType == WinSalGraphics::PRINTER), diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx index 293bfa247fb8..f370ff57a4bc 100644 --- a/vcl/win/gdi/winlayout.cxx +++ b/vcl/win/gdi/winlayout.cxx @@ -26,6 +26,8 @@ #include <opengl/texture.hxx> #include <opengl/win/gdiimpl.hxx> +#include "opengl/PackedTextureAtlas.hxx" + #include <vcl/opengl/OpenGLHelper.hxx> #include <win/salgdi.h> #include <win/saldata.hxx> @@ -74,13 +76,11 @@ const int GLYPH_SPACE_RATIO = 8; const int GLYPH_OFFSET_RATIO = GLYPH_SPACE_RATIO * 2; } -struct OpenGLGlyphCacheChunk +struct OpenGLGlyphDrawElement { - int mnFirstGlyph; // Must be int to handle non-BMP code points when mbRealGlyphIndices is false - int mnGlyphCount; - std::vector<Rectangle> maLocation; - std::vector<int> maLeftOverhangs; - std::shared_ptr<OpenGLTexture> mpTexture; + Rectangle maLocation; + int maLeftOverhangs; + OpenGLTexture maTexture; int mnBaselineOffset; int mnHeight; bool mbVertical; @@ -97,6 +97,41 @@ struct OpenGLGlyphCacheChunk } }; +class GlyphCache +{ +private: + static PackedTextureAtlasManager sPackedTextureAtlas; + std::unordered_map<int, OpenGLGlyphDrawElement> maOpenGLTextureCache; + +public: + GlyphCache() + {} + + void ReserveTextureSpace(OpenGLGlyphDrawElement& rElement, int nWidth, int nHeight) + { + rElement.maTexture = sPackedTextureAtlas.Reserve(nWidth, nHeight); + } + + void PutDrawElementInCache(const OpenGLGlyphDrawElement& rElement, int nGlyphIndex) + { + assert(!IsGlyphCached(nGlyphIndex)); + maOpenGLTextureCache[nGlyphIndex] = OpenGLGlyphDrawElement(rElement); + } + + OpenGLGlyphDrawElement& GetDrawElement(int nGlyphIndex) + { + assert(IsGlyphCached(nGlyphIndex)); + return maOpenGLTextureCache[nGlyphIndex]; + } + + bool IsGlyphCached(int nGlyphIndex) + { + return maOpenGLTextureCache.find(nGlyphIndex) != maOpenGLTextureCache.end(); + } +}; + +PackedTextureAtlasManager GlyphCache::sPackedTextureAtlas(2048, 2048); + // win32 specific physical font instance class WinFontInstance : public LogicalFontInstance { @@ -122,7 +157,6 @@ public: { return maScriptCache; } private: mutable SCRIPT_CACHE maScriptCache; - std::vector<OpenGLGlyphCacheChunk> maOpenGLGlyphCache; public: int GetCachedGlyphWidth( int nCharCode ) const; @@ -136,9 +170,15 @@ public: demo_atlas_t* mpGLyphyAtlas; demo_font_t* mpGLyphyFont; - bool GlyphIsCached(int nGlyphIndex) const; - bool AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, const WinLayout& rLayout, SalGraphics& rGraphics); - const OpenGLGlyphCacheChunk& GetCachedGlyphChunkFor(int nGlyphIndex) const; +private: + GlyphCache maGlyphCache; +public: + bool CacheGlyphToAtlas(bool bRealGlyphIndices, int nGlyphIndex, const WinLayout& rLayout, SalGraphics& rGraphics); + + GlyphCache& GetGlyphCache() + { + return maGlyphCache; + } private: IntMap maWidthMap; @@ -246,96 +286,6 @@ private: HDC mhDC; }; - -#ifdef SAL_LOG_INFO - -namespace { - -char ColorFor(COLORREF aColor) -{ - if (aColor == RGB(0xFF, 0xFF, 0xFF)) - return ' '; - else if (aColor == RGB(0x00, 0x00, 0x00)) - return 'X'; - - return '0' + (10*(GetRValue(aColor) + GetGValue(aColor) + GetBValue(aColor))) / (0xFF*3); -} - -void DumpGlyphBitmap(HDC hDC, const OpenGLGlyphCacheChunk& rChunk) -{ - HBITMAP hBitmap = static_cast<HBITMAP>(GetCurrentObject(hDC, OBJ_BITMAP)); - if (hBitmap == NULL) - { - SAL_WARN("vcl.gdi", "GetCurrentObject failed: " << WindowsErrorString(GetLastError())); - return; - } - - BITMAP aBitmap; - if (!GetObjectW(hBitmap, sizeof(aBitmap), &aBitmap)) - { - SAL_WARN("vcl.gdi", "GetObjectW failed: " << WindowsErrorString(GetLastError())); - return; - } - - SAL_INFO("vcl.gdi.opengl", "Bitmap " << hBitmap << ": " << aBitmap.bmWidth << "x" << aBitmap.bmHeight << ":"); - - std::ostringstream sLine("\n", std::ios_base::ate); - std::ostringstream sScale; - long nPrintWidth = std::min(125l, aBitmap.bmWidth); - for (long y = 0; y < aBitmap.bmHeight; y++) - { - if (y == rChunk.mnBaselineOffset + rChunk.getExtraOffset()) - sLine << "--------------------------\n"; - long n = 0; - for (long x = 0; x < nPrintWidth; x++) - { - // delimit. - for (size_t i = 0; i < rChunk.maLocation.size(); ++i) - { - if (x == rChunk.maLocation[i].Right()) - { - n = 0; - sLine << '|'; - if (y == 0) - sScale << ' '; - break; - } - } - sLine << ColorFor(GetPixel(hDC, x, y)); - if (y == 0) - sScale << (n++ % 10); - } - sLine << "\n"; - } - sLine << sScale.str(); - SAL_INFO("vcl.gdi.opengl", sLine.str()); -} - -} // anonymous namespace - -#endif // SAL_LOG_INFO - -template< typename charT, typename traits > -inline std::basic_ostream<charT, traits> & operator <<( - std::basic_ostream<charT, traits> & stream, const std::vector<OpenGLGlyphCacheChunk>& rCache ) -{ - stream << "{"; - for (auto i = rCache.cbegin(); i != rCache.cend(); ++i) - { - stream << "[" << i->mnFirstGlyph; - if (i->mnGlyphCount > 1) - stream << ".." << (i->mnFirstGlyph + i->mnGlyphCount - 1); - stream << "]"; - if (i+1 != rCache.cend()) - { - stream << ","; - assert(i->mnFirstGlyph + i->mnGlyphCount <= (i+1)->mnFirstGlyph); - } - } - - return stream << "}"; -} - inline void WinFontInstance::CacheGlyphWidth( int nCharCode, int nCharWidth ) { maWidthMap[ nCharCode ] = nCharWidth; @@ -349,60 +299,16 @@ inline int WinFontInstance::GetCachedGlyphWidth( int nCharCode ) const return it->second; } -bool WinFontInstance::GlyphIsCached(int nGlyphIndex) const +bool WinFontInstance::CacheGlyphToAtlas(bool bRealGlyphIndices, int nGlyphIndex, const WinLayout& rLayout, SalGraphics& rGraphics) { if (nGlyphIndex == DROPPED_OUTGLYPH) return true; - for (size_t i = 0; i < maOpenGLGlyphCache.size(); i++) - if (nGlyphIndex >= maOpenGLGlyphCache[i].mnFirstGlyph && - nGlyphIndex < maOpenGLGlyphCache[i].mnFirstGlyph + maOpenGLGlyphCache[i].mnGlyphCount) - return true; - - return false; -} - -bool WinFontInstance::AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, const WinLayout& rLayout, SalGraphics& rGraphics) -{ - const int DEFAULT_CHUNK_SIZE = 40; - - if (nGlyphIndex == DROPPED_OUTGLYPH) - return true; + OpenGLGlyphDrawElement aElement; + aElement.mbRealGlyphIndices = bRealGlyphIndices; - SAL_INFO("vcl.gdi.opengl", "this=" << this << " " << nGlyphIndex << " old: " << maOpenGLGlyphCache); - - auto n = maOpenGLGlyphCache.begin(); - while (n != maOpenGLGlyphCache.end() && - nGlyphIndex > n->mnFirstGlyph) - ++n; - assert(n == maOpenGLGlyphCache.end() || nGlyphIndex < n->mnFirstGlyph); - - int nCount = DEFAULT_CHUNK_SIZE; - if (n != maOpenGLGlyphCache.end() && nGlyphIndex + nCount >= n->mnFirstGlyph) - nCount = n->mnFirstGlyph - nGlyphIndex; - - if (nCount < DEFAULT_CHUNK_SIZE) - { - if (n == maOpenGLGlyphCache.begin()) - { - nGlyphIndex = std::max(0, n->mnFirstGlyph - DEFAULT_CHUNK_SIZE); - } - else - { - nGlyphIndex = std::max(n[-1].mnFirstGlyph + n[-1].mnGlyphCount, - n->mnFirstGlyph - DEFAULT_CHUNK_SIZE); - } - nCount = n->mnFirstGlyph - nGlyphIndex; - } - - OpenGLGlyphCacheChunk aChunk; - aChunk.mnFirstGlyph = nGlyphIndex; - aChunk.mnGlyphCount = nCount; - aChunk.mbRealGlyphIndices = bRealGlyphIndices; - - std::vector<uint32_t> aCodePointsOrGlyphIndices(nCount); - for (int i = 0; i < nCount; i++) - aCodePointsOrGlyphIndices[i] = nGlyphIndex + i; + std::vector<uint32_t> aCodePointsOrGlyphIndices(1); + aCodePointsOrGlyphIndices[0] = nGlyphIndex; HDC hDC = CreateCompatibleDC(rLayout.mhDC); if (hDC == NULL) @@ -441,7 +347,7 @@ bool WinFontInstance::AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, return false; } } - std::vector<WORD> aGlyphIndices(nCount); + std::vector<WORD> aGlyphIndices(1); // Fetch the ink boxes and calculate the size of the atlas. if (!bRealGlyphIndices) { @@ -453,69 +359,60 @@ bool WinFontInstance::AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, } else { - for (int i = 0; i < nCount; i++) - aGlyphIndices[i] = aCodePointsOrGlyphIndices[i]; + aGlyphIndices[0] = aCodePointsOrGlyphIndices[0]; } Rectangle bounds(0, 0, 0, 0); - auto aInkBoxes = pTxt->GetGlyphInkBoxes(aGlyphIndices.data(), aGlyphIndices.data() + nCount); + auto aInkBoxes = pTxt->GetGlyphInkBoxes(aGlyphIndices.data(), aGlyphIndices.data() + 1); for (auto &box : aInkBoxes) bounds.Union(box + Point(bounds.Right(), 0)); // bounds.Top() is the offset from the baseline at (0,0) to the top of the // inkbox. - aChunk.mnBaselineOffset = -bounds.Top(); - aChunk.mnHeight = bounds.getHeight(); - aChunk.mbVertical = false; - - aChunk.maLeftOverhangs.resize(nCount); - aChunk.maLocation.resize(nCount); + aElement.mnBaselineOffset = -bounds.Top(); + aElement.mnHeight = bounds.getHeight(); + aElement.mbVertical = false; // Try hard to avoid overlap as we want to be able to use // individual rectangles for each glyph. The ABC widths don't // take anti-aliasing into consideration. Let's hope that leaving // "extra" space between glyphs will help. - std::vector<float> aGlyphAdv(nCount); // offsets between glyphs - std::vector<DWRITE_GLYPH_OFFSET> aGlyphOffset(nCount, DWRITE_GLYPH_OFFSET{0.0f,0.0f}); - std::vector<int> aEnds(nCount); // end of each glyph box + std::vector<float> aGlyphAdv(1); // offsets between glyphs + std::vector<DWRITE_GLYPH_OFFSET> aGlyphOffset(1, DWRITE_GLYPH_OFFSET{0.0f, 0.0f}); + std::vector<int> aEnds(1); // end of each glyph box float totWidth = 0; - for (int i = 0; i < nCount; ++i) { - int overhang = aInkBoxes[i].Left(); - int blackWidth = aInkBoxes[i].getWidth(); // width of non-AA pixels - aChunk.maLeftOverhangs[i] = overhang; + int overhang = aInkBoxes[0].Left(); + int blackWidth = aInkBoxes[0].getWidth(); // width of non-AA pixels + aElement.maLeftOverhangs = overhang; - aGlyphAdv[i] = blackWidth + aChunk.getExtraSpace(); - aGlyphOffset[i].advanceOffset = -overhang; + aGlyphAdv[0] = blackWidth + aElement.getExtraSpace(); + aGlyphOffset[0].advanceOffset = -overhang; - totWidth += aGlyphAdv[i]; - aEnds[i] = totWidth; + totWidth += aGlyphAdv[0]; + aEnds[0] = totWidth; } - // Leave extra space also at top and bottom - int nBitmapWidth = totWidth, - nBitmapHeight = bounds.getHeight() + aChunk.getExtraSpace(); + int nBitmapWidth = totWidth; + int nBitmapHeight = bounds.getHeight() + aElement.getExtraSpace(); - aChunk.maLocation.resize(nCount); UINT nPos = 0; - for (int i = 0; i < nCount; i++) + + // FIXME: really I don't get why 'vertical' makes any difference [!] what does it mean !? + if (aElement.mbVertical) { - // FIXME: really I don't get why 'vertical' makes any difference [!] what does it mean !? - if (aChunk.mbVertical) - { - aChunk.maLocation[i].Left() = 0; - aChunk.maLocation[i].Right() = nBitmapWidth; - aChunk.maLocation[i].Top() = nPos; - aChunk.maLocation[i].Bottom() = nPos + aGlyphAdv[i] + aChunk.maLeftOverhangs[i]; - } - else - { - aChunk.maLocation[i].Left() = nPos; - aChunk.maLocation[i].Right() = aEnds[i]; - aChunk.maLocation[i].Top() = 0; - aChunk.maLocation[i].Bottom() = bounds.getHeight() + aChunk.getExtraSpace(); - } - nPos = aEnds[i]; + aElement.maLocation.Left() = 0; + aElement.maLocation.Right() = nBitmapWidth; + aElement.maLocation.Top() = nPos; + aElement.maLocation.Bottom() = nPos + aGlyphAdv[0] + aElement.maLeftOverhangs; + } + else + { + aElement.maLocation.Left() = nPos; + aElement.maLocation.Right() = aEnds[0]; + aElement.maLocation.Top() = 0; + aElement.maLocation.Bottom() = bounds.getHeight() + aElement.getExtraSpace(); } + nPos = aEnds[0]; OpenGLCompatibleDC aDC(rGraphics, 0, 0, nBitmapWidth, nBitmapHeight); @@ -536,11 +433,15 @@ bool WinFontInstance::AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, return false; } - D2D1_POINT_2F baseline = { aChunk.getExtraOffset(), aChunk.getExtraOffset() + aChunk.mnBaselineOffset }; + D2D1_POINT_2F baseline = { + aElement.getExtraOffset(), + aElement.getExtraOffset() + aElement.mnBaselineOffset + }; + DWRITE_GLYPH_RUN glyphs = { pTxt->GetFontFace(), pTxt->GetEmHeight(), - nCount, + 1, aGlyphIndices.data(), aGlyphAdv.data(), aGlyphOffset.data(), @@ -550,11 +451,11 @@ bool WinFontInstance::AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, pRT->BeginDraw(); pRT->DrawGlyphRun(baseline, &glyphs, pBrush); - HRESULT hr = pRT->EndDraw(); + HRESULT hResult = pRT->EndDraw(); pBrush->Release(); - switch (hr) + switch (hResult) { case S_OK: break; @@ -571,25 +472,14 @@ bool WinFontInstance::AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, pTxt->ReleaseFont(); - aChunk.mpTexture = std::unique_ptr<OpenGLTexture>(aDC.getTexture()); - - maOpenGLGlyphCache.insert(n, aChunk); + maGlyphCache.ReserveTextureSpace(aElement, nBitmapWidth, nBitmapHeight); + aDC.copyToTexture(aElement.maTexture); + maGlyphCache.PutDrawElementInCache(aElement, nGlyphIndex); SelectFont(aDC.getCompatibleHDC(), hOrigFont); if (hNonAntialiasedFont != NULL) DeleteObject(hNonAntialiasedFont); -#ifdef SAL_LOG_INFO - SAL_INFO("vcl.gdi.opengl", "this=" << this << " now: " << maOpenGLGlyphCache); - DumpGlyphBitmap(aDC.getCompatibleHDC(), aChunk); - { - std::ostringstream sLine; - for (int i = 0; i < nCount; i++) - sLine << aGlyphAdv[i] << ":" << aChunk.maLeftOverhangs[i] << " "; - SAL_INFO("vcl.gdi.opengl", "DX:offset : " << sLine.str()); - } -#endif - return true; } @@ -1288,16 +1178,6 @@ void SimpleWinLayout::Simplify( bool /*bIsBase*/ ) mnWidth = mnBaseAdv = 0; } -const OpenGLGlyphCacheChunk& WinFontInstance::GetCachedGlyphChunkFor(int nGlyphIndex) const -{ - auto i = maOpenGLGlyphCache.cbegin(); - while (i != maOpenGLGlyphCache.cend() && nGlyphIndex >= i->mnFirstGlyph + i->mnGlyphCount) - ++i; - assert(i != maOpenGLGlyphCache.cend()); - assert(nGlyphIndex >= i->mnFirstGlyph && nGlyphIndex < i->mnFirstGlyph + i->mnGlyphCount); - return *i; -} - void WinFontInstance::setupGLyphy(HDC hDC) { if (mbGLyphySetupCalled) @@ -1531,11 +1411,9 @@ bool SimpleWinLayout::CacheGlyphs(SalGraphics& rGraphics) const nCodePoint = mpOutGlyphs[i]; } - if (mrWinFontEntry.GlyphIsCached(nCodePoint)) - continue; + if (!mrWinFontEntry.GetGlyphCache().IsGlyphCached(nCodePoint)) + assert(mrWinFontEntry.CacheGlyphToAtlas(false, nCodePoint, *this, rGraphics)); - if (!mrWinFontEntry.AddChunkOfGlyphs(false, nCodePoint, *this, rGraphics)) - return false; } return true; @@ -1577,18 +1455,16 @@ bool SimpleWinLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const nCodePoint = mpOutGlyphs[i]; } - assert(mrWinFontEntry.GlyphIsCached(nCodePoint)); + OpenGLGlyphDrawElement& rElement(mrWinFontEntry.GetGlyphCache().GetDrawElement(nCodePoint)); + OpenGLTexture& rTexture = rElement.maTexture; - const OpenGLGlyphCacheChunk& rChunk = mrWinFontEntry.GetCachedGlyphChunkFor(nCodePoint); - const int n = nCodePoint - rChunk.mnFirstGlyph; + SalTwoRect a2Rects(0, 0, + rTexture.GetWidth(), rTexture.GetHeight(), + nAdvance + aPos.X() - rElement.getExtraOffset() + rElement.maLeftOverhangs, + aPos.Y() - rElement.mnBaselineOffset - rElement.getExtraOffset(), + rTexture.GetWidth(), rTexture.GetHeight()); - SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(), - rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(), - nAdvance + aPos.X() - rChunk.getExtraOffset() + rChunk.maLeftOverhangs[n], - aPos.Y() - rChunk.mnBaselineOffset - rChunk.getExtraOffset(), - rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ??? - - pImpl->DeferredTextDraw(*rChunk.mpTexture, salColor, a2Rects); + pImpl->DeferredTextDraw(rTexture, salColor, a2Rects); nAdvance += mpGlyphAdvances[i]; } @@ -2801,11 +2677,9 @@ bool UniscribeLayout::CacheGlyphs(SalGraphics& rGraphics) const { for (int i = 0; i < mnGlyphCount; i++) { - if (mrWinFontEntry.GlyphIsCached(mpOutGlyphs[i])) - continue; - - if (!mrWinFontEntry.AddChunkOfGlyphs(true, mpOutGlyphs[i], *this, rGraphics)) - return false; + int nCodePoint = mpOutGlyphs[i]; + if (!mrWinFontEntry.GetGlyphCache().IsGlyphCached(nCodePoint)) + assert(mrWinFontEntry.CacheGlyphToAtlas(true, nCodePoint, *this, rGraphics)); } } @@ -3093,28 +2967,30 @@ bool UniscribeLayout::DrawCachedGlyphsUsingTextures(SalGraphics& rGraphics) cons if (mpOutGlyphs[i] == DROPPED_OUTGLYPH) continue; - assert(mrWinFontEntry.GlyphIsCached(mpOutGlyphs[i])); - - const OpenGLGlyphCacheChunk& rChunk = mrWinFontEntry.GetCachedGlyphChunkFor(mpOutGlyphs[i]); - const int n = mpOutGlyphs[i] - rChunk.mnFirstGlyph; + OpenGLGlyphDrawElement& rElement = mrWinFontEntry.GetGlyphCache().GetDrawElement(mpOutGlyphs[i]); + OpenGLTexture& rTexture = rElement.maTexture; - if (rChunk.mbVertical) + if (rElement.mbVertical) { - SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(), - rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(), - aPos.X() + rChunk.maLeftOverhangs[n], nAdvance + aPos.Y(), - rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ??? - pImpl->DeferredTextDraw(*rChunk.mpTexture, salColor, a2Rects); + SalTwoRect a2Rects(0, 0, + rTexture.GetWidth(), rTexture.GetHeight(), + aPos.X() + rElement.maLeftOverhangs, + nAdvance + aPos.Y(), + rTexture.GetWidth(), rTexture.GetHeight()); + + pImpl->DeferredTextDraw(rTexture, salColor, a2Rects); } else { - SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(), - rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(), - nAdvance + aPos.X() + mpGlyphOffsets[i].du - rChunk.getExtraOffset() + rChunk.maLeftOverhangs[n], - aPos.Y() + mpGlyphOffsets[i].dv - rChunk.mnBaselineOffset - rChunk.getExtraOffset(), - rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ??? - pImpl->DeferredTextDraw(*rChunk.mpTexture, salColor, a2Rects); + SalTwoRect a2Rects(0, 0, + rTexture.GetWidth(), rTexture.GetHeight(), + nAdvance + aPos.X() + mpGlyphOffsets[i].du - rElement.getExtraOffset() + rElement.maLeftOverhangs, + aPos.Y() + mpGlyphOffsets[i].dv - rElement.mnBaselineOffset - rElement.getExtraOffset(), + rTexture.GetWidth(), rTexture.GetHeight()); + + pImpl->DeferredTextDraw(rTexture, salColor, a2Rects); } + nAdvance += pGlyphWidths[i]; } } |