[Libreoffice-commits] core.git: 4 commits - vcl/inc vcl/win
Tor Lillqvist
tml at collabora.com
Tue Aug 18 23:28:35 PDT 2015
vcl/inc/win/salgdi.h | 1
vcl/win/source/gdi/winlayout.cxx | 347 +++++++++++++++++++++++++++++++++++++++
vcl/win/source/gdi/winlayout.hxx | 8
3 files changed, 355 insertions(+), 1 deletion(-)
New commits:
commit 239d4e0cbd7d0c4e3504528b8dcf5e10fbea9a0b
Author: Tor Lillqvist <tml at collabora.com>
Date: Wed Aug 19 09:18:37 2015 +0300
More hacks to glyph rendering for caching with OpenGL on Windows
Change-Id: I934ad7453f35909f4c3ad999e33453b5b6032480
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 0ab9cd9..7f4c4a4 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -160,7 +160,10 @@ inline std::basic_ostream<charT, traits> & operator <<(
stream << "{";
for (auto i = rCache.cbegin(); i != rCache.cend(); ++i)
{
- stream << "[" << i->mnFirstGlyph << ".." << (i->mnFirstGlyph + i->mnGlyphCount - 1) << "]";
+ stream << "[" << i->mnFirstGlyph;
+ if (i->mnGlyphCount > 1)
+ stream << ".." << (i->mnFirstGlyph + i->mnGlyphCount - 1);
+ stream << "]";
if (i+1 != rCache.cend())
{
stream << ",";
@@ -278,10 +281,16 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
int totWidth = 0;
for (int i = 0; i < nCount; i++)
{
- aDX[i] = std::abs(aABC[i].abcA) + aABC[i].abcB + std::abs(aABC[i].abcC);
+ aDX[i] = aABC[i].abcB + std::abs(aABC[i].abcC);
+ if (i == 0)
+ aDX[0] += std::abs(aABC[0].abcA);
+ if (i < nCount-1)
+ aDX[i] += std::abs(aABC[i+1].abcA);
totWidth += aDX[i];
}
+ SAL_INFO("vcl.gdi.opengl", "aSize=(" << aSize.cx << "," << aSize.cy << ") totWidth=" << totWidth);
+
if (SelectObject(hDC, hOrigFont) == NULL)
SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
if (!DeleteDC(hDC))
commit df42d08191fd76b38d58a317f9aca804e10df062
Author: Tor Lillqvist <tml at collabora.com>
Date: Tue Aug 18 13:43:27 2015 +0300
More hacking on OpenGL glyph caching on Windows
Now text looks better, for instance the lower-case "t" glyphs on the
Start Centre aren't totally weird any more. But for instance the tip
of the hook of "j" leaks into the "i" texture. I guess I really would
need to render glyphs one by one.
Change-Id: I69ae2d2f7c559530bcfdfc1a4915503fcb3ab4af
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index e32b8b5..0ab9cd9 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -204,7 +204,7 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
if (nGlyphIndex == DROPPED_OUTGLYPH)
return true;
- SAL_INFO("vcl.gdi.opengl", "AddChunkOfGlyphs " << this << " " << nGlyphIndex << " old: " << maOpenGLGlyphCache);
+ SAL_INFO("vcl.gdi.opengl", "this=" << this << " " << nGlyphIndex << " old: " << maOpenGLGlyphCache);
auto n = maOpenGLGlyphCache.begin();
while (n != maOpenGLGlyphCache.end() &&
@@ -262,12 +262,32 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
return false;
}
+ std::vector<ABC> aABC(nCount);
+ if (!GetCharABCWidthsI(hDC, 0, nCount, aGlyphIndices.data(), aABC.data()))
+ {
+ SAL_WARN("vcl.gdi", "GetCharABCWidthsI failed: " << WindowsErrorString(GetLastError()));
+ return false;
+ }
+
+ for (int i = 0; i < nCount; i++)
+ std::cerr << aABC[i].abcA << ":" << aABC[i].abcB << ":" << aABC[i].abcC << " ";
+ std::cerr << std::endl;
+
+ // Avoid kerning as we want to be able to use individual rectangles for each glyph
+ std::vector<int> aDX(nCount);
+ int totWidth = 0;
+ for (int i = 0; i < nCount; i++)
+ {
+ aDX[i] = std::abs(aABC[i].abcA) + aABC[i].abcB + std::abs(aABC[i].abcC);
+ totWidth += aDX[i];
+ }
+
if (SelectObject(hDC, hOrigFont) == NULL)
SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
if (!DeleteDC(hDC))
SAL_WARN("vcl.gdi", "DeleteDC failed: " << WindowsErrorString(GetLastError()));
- OpenGLCompatibleDC aDC(rGraphics, 0, 0, aSize.cx, aSize.cy);
+ OpenGLCompatibleDC aDC(rGraphics, 0, 0, totWidth, aSize.cy);
hOrigFont = SelectFont(aDC.getCompatibleHDC(), rLayout.mhFont);
if (hOrigFont == NULL)
@@ -279,21 +299,6 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0));
SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255));
- std::vector<ABC> aABC(nCount);
- if (!GetCharABCWidthsI(aDC.getCompatibleHDC(), 0, nCount, aGlyphIndices.data(), aABC.data()))
- {
- SAL_WARN("vcl.gdi", "GetCharABCWidthsI failed: " << WindowsErrorString(GetLastError()));
- return false;
- }
-
- for (int i = 0; i < nCount; i++)
- std::cerr << aABC[i].abcA << ":" << aABC[i].abcB << ":" << aABC[i].abcC << " ";
- std::cerr << std::endl;
-
- // Avoid kerning as we want to be able to use individual rectangles for each glyph
- std::vector<int> aDX(nCount);
- for (int i = 0; i < nCount; i++)
- aDX[i] = std::abs(aABC[i].abcA) + aABC[i].abcB + std::abs(aABC[i].abcC);
if (!ExtTextOutW(aDC.getCompatibleHDC(), 0, 0, ETO_GLYPH_INDEX, NULL, aGlyphIndices.data(), nCount, aDX.data()))
{
SAL_WARN("vcl.gdi", "ExtTextOutW failed: " << WindowsErrorString(GetLastError()));
@@ -317,7 +322,7 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
SelectFont(aDC.getCompatibleHDC(), hOrigFont);
- SAL_INFO("vcl.gdi.opengl", "AddChunkOfGlyphs " << this << " now: " << maOpenGLGlyphCache << DumpGlyphBitmap(aChunk, aDC.getCompatibleHDC()));
+ SAL_INFO("vcl.gdi.opengl", "this=" << this << " now: " << maOpenGLGlyphCache << DumpGlyphBitmap(aChunk, aDC.getCompatibleHDC()));
return true;
}
commit b3c8095de5cf8c8030e3bac0532363def3070c3e
Author: Tor Lillqvist <tml at collabora.com>
Date: Mon Aug 17 18:23:11 2015 +0300
Add FIXME comment and bin an #if 0 snippet
Change-Id: I0bbea4ef62c8e94d8b8f1bfb440712da5839e532
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 6f8b4ca..e32b8b5 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -1579,6 +1579,8 @@ bool UniscribeLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const
pImpl->PreDraw();
+ // FIXME: This code snippet is mostly copied from the one in
+ // UniscribeLayout::DrawTextImpl. Should be factored out.
int nBaseClusterOffset = 0;
int nBaseGlyphPos = -1;
for( int nItem = 0; nItem < mnItemCount; ++nItem )
@@ -1626,16 +1628,6 @@ bool UniscribeLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const
pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects);
nAdvance += mpGlyphAdvances[i];
}
-#if 0
- ScriptTextOut(hDC, &rScriptCache,
- aPos.X(), aPos.Y(), 0, NULL,
- &rVisualItem.mpScriptItem->a, NULL, 0,
- mpOutGlyphs + nMinGlyphPos,
- nEndGlyphPos - nMinGlyphPos,
- mpGlyphAdvances + nMinGlyphPos,
- mpJustifications ? mpJustifications + nMinGlyphPos : NULL,
- mpGlyphOffsets + nMinGlyphPos);
-#endif
}
pImpl->PostDraw();
commit d4ade4aeb60617b620faf21f08605b6feb069cce
Author: Tor Lillqvist <tml at collabora.com>
Date: Mon Aug 17 17:02:35 2015 +0300
Initial hack for OpenGL glyph caching on Windows
Shows text roughly correctly, but many problems. Conditional at
run-time on the SAL_ENABLE_GLYPH_CACHING environment variable in
addition to SAL_FORCEGL.
One obvious thing that needs fixing is making sure that the glyphs are
rendered into the texture without overlap. Compensating negative
values in the ABC::abcA and ABC::abdC width is not enough.
Also, the cache should be changed to actually have "cache"
functionality, i.e. entries should expire based on some criterion.
Change-Id: I66a37d3354a09011a654f15a7d2bd8efaa14ad1e
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 7d05d23..852b470 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -187,6 +187,7 @@ class WinSalGraphics : public SalGraphics
friend class ScopedFont;
friend class OpenGLCompatibleDC;
friend class WinLayout;
+ friend class UniscribeLayout;
protected:
std::unique_ptr<SalGraphicsImpl> mpImpl;
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 89503f3..6f8b4ca 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -22,6 +22,8 @@
#include "osl/module.h"
#include "osl/file.h"
+#include <comphelper/windowserrorstring.hxx>
+
#include <opengl/texture.hxx>
#include <opengl/win/gdiimpl.hxx>
#include <vcl/opengl/OpenGLHelper.hxx>
@@ -32,6 +34,8 @@
#include "sallayout.hxx"
#include <cstdio>
+#include <cstdlib>
+
#include <sal/alloca.h>
#include <algorithm>
@@ -54,6 +58,14 @@ typedef std::unordered_map<int,int> IntMap;
#include <config_mingw.h>
+struct OpenGLGlyphCacheChunk
+{
+ WORD mnFirstGlyph;
+ int mnGlyphCount;
+ std::vector<Rectangle> maLocation;
+ std::shared_ptr<OpenGLTexture> mpTexture;
+};
+
// win32 specific physical font instance
class ImplWinFontEntry : public ImplFontEntry
{
@@ -77,6 +89,7 @@ public:
{ return maScriptCache; }
private:
mutable SCRIPT_CACHE maScriptCache;
+ std::vector<OpenGLGlyphCacheChunk> maOpenGLGlyphCache;
public:
int GetCachedGlyphWidth( int nCharCode ) const;
@@ -90,8 +103,74 @@ private:
IntMap maWidthMap;
mutable int mnMinKashidaWidth;
mutable int mnMinKashidaGlyph;
+
+public:
+ bool GlyphIsCached(int nGlyphIndex) const;
+ bool AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayout, SalGraphics& rGraphics);
+ const OpenGLGlyphCacheChunk& GetCachedGlyphChunkFor(int nGlyphIndex) const;
};
+char ColorFor(COLORREF aColor)
+{
+ if (aColor == RGB(0xFF, 0xFF, 0xFF))
+ return ' ';
+ return '0' + 10*((GetRValue(aColor) + GetGValue(aColor) + GetBValue(aColor)) / (0xFF*3));
+}
+
+OUString DumpGlyphBitmap(OpenGLGlyphCacheChunk& rChunk, HDC hDC)
+{
+ 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 "";
+ }
+
+ std::cerr << "Bitmap " << hBitmap << ": " << aBitmap.bmWidth << "x" << aBitmap.bmHeight << ":" << std::endl;
+ int nPos = 0;
+ for (int i = 1; i < rChunk.mnGlyphCount && nPos < 75; i++)
+ {
+ for (int j = nPos; j < rChunk.maLocation[i].Left(); j++)
+ std::cerr << " ";
+ std::cerr << "!";
+ nPos = rChunk.maLocation[i].Left() + 1;
+ }
+ std::cerr << std::endl;
+
+ for (long y = 0; y < std::min(20l, aBitmap.bmHeight); y++)
+ {
+ for (long x = 0; x < std::min(75l, aBitmap.bmWidth); x++)
+ std::cerr << ColorFor(GetPixel(hDC, x, y));
+ std::cerr << std::endl;
+ }
+ return "";
+}
+
+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 << ".." << (i->mnFirstGlyph + i->mnGlyphCount - 1) << "]";
+ if (i+1 != rCache.cend())
+ {
+ stream << ",";
+ assert(i->mnFirstGlyph + i->mnGlyphCount <= (i+1)->mnFirstGlyph);
+ }
+ }
+
+ return stream << "}";
+}
+
inline void ImplWinFontEntry::CacheGlyphWidth( int nCharCode, int nCharWidth )
{
maWidthMap[ nCharCode ] = nCharWidth;
@@ -105,6 +184,154 @@ inline int ImplWinFontEntry::GetCachedGlyphWidth( int nCharCode ) const
return it->second;
}
+bool ImplWinFontEntry::GlyphIsCached(int nGlyphIndex) const
+{
+ 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 ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayout, SalGraphics& rGraphics)
+{
+ const int DEFAULT_CHUNK_SIZE = 20;
+
+ if (nGlyphIndex == DROPPED_OUTGLYPH)
+ return true;
+
+ SAL_INFO("vcl.gdi.opengl", "AddChunkOfGlyphs " << 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;
+
+ std::vector<WORD> aGlyphIndices(nCount);
+ for (int i = 0; i < nCount; i++)
+ aGlyphIndices[i] = nGlyphIndex + i;
+
+ HDC hDC = CreateCompatibleDC(rLayout.mhDC);
+ if (hDC == NULL)
+ {
+ SAL_WARN("vcl.gdi", "CreateCompatibleDC failed: " << WindowsErrorString(GetLastError()));
+ return false;
+ }
+ HFONT hOrigFont = static_cast<HFONT>(SelectObject(hDC, rLayout.mhFont));
+ if (hOrigFont == NULL)
+ {
+ SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
+ DeleteDC(hDC);
+ return false;
+ }
+
+ SIZE aSize;
+
+ if (!GetTextExtentExPointI(hDC, aGlyphIndices.data(), nCount, 0, NULL, NULL, &aSize))
+ {
+ SAL_WARN("vcl.gdi", "GetTextExtentExPointI failed: " << WindowsErrorString(GetLastError()));
+ SelectObject(hDC, hOrigFont);
+ DeleteDC(hDC);
+ return false;
+ }
+
+ if (SelectObject(hDC, hOrigFont) == NULL)
+ SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
+ if (!DeleteDC(hDC))
+ SAL_WARN("vcl.gdi", "DeleteDC failed: " << WindowsErrorString(GetLastError()));
+
+ OpenGLCompatibleDC aDC(rGraphics, 0, 0, aSize.cx, aSize.cy);
+
+ hOrigFont = SelectFont(aDC.getCompatibleHDC(), rLayout.mhFont);
+ if (hOrigFont == NULL)
+ {
+ SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
+ return false;
+ }
+
+ SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0));
+ SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255));
+
+ std::vector<ABC> aABC(nCount);
+ if (!GetCharABCWidthsI(aDC.getCompatibleHDC(), 0, nCount, aGlyphIndices.data(), aABC.data()))
+ {
+ SAL_WARN("vcl.gdi", "GetCharABCWidthsI failed: " << WindowsErrorString(GetLastError()));
+ return false;
+ }
+
+ for (int i = 0; i < nCount; i++)
+ std::cerr << aABC[i].abcA << ":" << aABC[i].abcB << ":" << aABC[i].abcC << " ";
+ std::cerr << std::endl;
+
+ // Avoid kerning as we want to be able to use individual rectangles for each glyph
+ std::vector<int> aDX(nCount);
+ for (int i = 0; i < nCount; i++)
+ aDX[i] = std::abs(aABC[i].abcA) + aABC[i].abcB + std::abs(aABC[i].abcC);
+ if (!ExtTextOutW(aDC.getCompatibleHDC(), 0, 0, ETO_GLYPH_INDEX, NULL, aGlyphIndices.data(), nCount, aDX.data()))
+ {
+ SAL_WARN("vcl.gdi", "ExtTextOutW failed: " << WindowsErrorString(GetLastError()));
+ return false;
+ }
+
+ aChunk.maLocation.resize(nCount);
+ UINT nPos = 0;
+ for (int i = 0; i < nCount; i++)
+ {
+ aChunk.maLocation[i].Left() = nPos;
+ aChunk.maLocation[i].Right() = nPos + aDX[i];
+ nPos = aChunk.maLocation[i].Right();
+ aChunk.maLocation[i].Top() = 0;
+ aChunk.maLocation[i].Bottom() = aSize.cy;
+ }
+
+ aChunk.mpTexture = std::unique_ptr<OpenGLTexture>(aDC.getTexture());
+
+ maOpenGLGlyphCache.insert(n, aChunk);
+
+ SelectFont(aDC.getCompatibleHDC(), hOrigFont);
+
+ SAL_INFO("vcl.gdi.opengl", "AddChunkOfGlyphs " << this << " now: " << maOpenGLGlyphCache << DumpGlyphBitmap(aChunk, aDC.getCompatibleHDC()));
+
+ return true;
+}
+
+const OpenGLGlyphCacheChunk& ImplWinFontEntry::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;
+}
+
WinLayout::WinLayout(HDC hDC, const ImplWinFontData& rWFD, ImplWinFontEntry& rWFE, bool bUseOpenGL)
: mhDC( hDC ),
mhFont( (HFONT)GetCurrentObject(hDC,OBJ_FONT) ),
@@ -157,6 +384,11 @@ void WinLayout::DrawText(SalGraphics& rGraphics) const
// no OpenGL, just classic rendering
DrawTextImpl(hDC);
}
+ else if (CacheGlyphs(rGraphics) &&
+ DrawCachedGlyphs(rGraphics))
+ {
+ // Nothing
+ }
else
{
// We have to render the text to a hidden texture, and draw it.
@@ -1311,6 +1543,105 @@ void UniscribeLayout::DrawTextImpl(HDC hDC) const
DeleteFont(SelectFont(hDC, hOrigFont));
}
+bool UniscribeLayout::CacheGlyphs(SalGraphics& rGraphics) const
+{
+ const bool bDoGlyphCaching = (std::getenv("SAL_ENABLE_GLYPH_CACHING") != NULL);
+
+ if (!bDoGlyphCaching)
+ return false;
+
+ for (int i = 0; i < mnGlyphCount; i++)
+ {
+ if (mrWinFontEntry.GlyphIsCached(mpOutGlyphs[i]))
+ continue;
+
+ if (!mrWinFontEntry.AddChunkOfGlyphs(mpOutGlyphs[i], *this, rGraphics))
+ return false;
+ }
+
+ return true;
+}
+
+bool UniscribeLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const
+{
+ WinSalGraphics& rWinGraphics = static_cast<WinSalGraphics&>(rGraphics);
+ HDC hDC = rWinGraphics.getHDC();
+
+ Rectangle aRect;
+ GetBoundRect(rGraphics, aRect);
+
+ COLORREF color = GetTextColor(hDC);
+ SalColor salColor = MAKE_SALCOLOR(GetRValue(color), GetGValue(color), GetBValue(color));
+
+ WinOpenGLSalGraphicsImpl *pImpl = dynamic_cast<WinOpenGLSalGraphicsImpl*>(rWinGraphics.mpImpl.get());
+ if (!pImpl)
+ return false;
+
+ pImpl->PreDraw();
+
+ int nBaseClusterOffset = 0;
+ int nBaseGlyphPos = -1;
+ for( int nItem = 0; nItem < mnItemCount; ++nItem )
+ {
+ const VisualItem& rVisualItem = mpVisualItems[ nItem ];
+
+ // skip if there is nothing to display
+ int nMinGlyphPos, nEndGlyphPos;
+ if( !GetItemSubrange( rVisualItem, nMinGlyphPos, nEndGlyphPos ) )
+ continue;
+
+ if( nBaseGlyphPos < 0 )
+ {
+ // adjust draw position relative to cluster start
+ if( rVisualItem.IsRTL() )
+ nBaseGlyphPos = nEndGlyphPos - 1;
+ else
+ nBaseGlyphPos = nMinGlyphPos;
+
+ int i = mnMinCharPos;
+ while( (--i >= rVisualItem.mnMinCharPos)
+ && (nBaseGlyphPos == mpLogClusters[i]) )
+ nBaseClusterOffset += mpCharWidths[i];
+
+ if( !rVisualItem.IsRTL() )
+ nBaseClusterOffset = -nBaseClusterOffset;
+ }
+
+ // now draw the matching glyphs in this item
+ Point aRelPos( rVisualItem.mnXOffset + nBaseClusterOffset, 0 );
+ Point aPos = GetDrawPosition( aRelPos );
+
+ int nAdvance = 0;
+ for (int i = nMinGlyphPos; i < nEndGlyphPos; i++)
+ {
+ assert(mrWinFontEntry.GlyphIsCached(mpOutGlyphs[i]));
+
+ const OpenGLGlyphCacheChunk& rChunk = mrWinFontEntry.GetCachedGlyphChunkFor(mpOutGlyphs[i]);
+ const int n = mpOutGlyphs[i] - rChunk.mnFirstGlyph;
+
+ SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(),
+ rChunk.maLocation[n].GetWidth(), rChunk.maLocation[n].GetHeight(),
+ nAdvance + aPos.X() + mpGlyphOffsets[i].du, aPos.Y() + mpGlyphOffsets[i].dv - rChunk.maLocation[n].GetHeight(),
+ rChunk.maLocation[n].GetWidth(), rChunk.maLocation[n].GetHeight()); // ???
+ pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects);
+ nAdvance += mpGlyphAdvances[i];
+ }
+#if 0
+ ScriptTextOut(hDC, &rScriptCache,
+ aPos.X(), aPos.Y(), 0, NULL,
+ &rVisualItem.mpScriptItem->a, NULL, 0,
+ mpOutGlyphs + nMinGlyphPos,
+ nEndGlyphPos - nMinGlyphPos,
+ mpGlyphAdvances + nMinGlyphPos,
+ mpJustifications ? mpJustifications + nMinGlyphPos : NULL,
+ mpGlyphOffsets + nMinGlyphPos);
+#endif
+ }
+ pImpl->PostDraw();
+
+ return true;
+}
+
DeviceCoordinate UniscribeLayout::FillDXArray( DeviceCoordinate* pDXArray ) const
{
// calculate width of the complete layout
@@ -1954,6 +2285,16 @@ void GraphiteWinLayout::DrawTextImpl(HDC hDC) const
DeleteFont(SelectFont(hDC, hOrigFont));
}
+bool GraphiteWinLayout::CacheGlyphs(SalGraphics& /*rGraphics*/) const
+{
+ return false;
+}
+
+bool GraphiteWinLayout::DrawCachedGlyphs(SalGraphics& /*rGraphics*/) const
+{
+ return false;
+}
+
sal_Int32 GraphiteWinLayout::GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const
{
sal_Int32 nBreak = maImpl.GetTextBreak(nMaxWidth, nCharExtra, nFactor);
diff --git a/vcl/win/source/gdi/winlayout.hxx b/vcl/win/source/gdi/winlayout.hxx
index 7819eae..8855e37 100644
--- a/vcl/win/source/gdi/winlayout.hxx
+++ b/vcl/win/source/gdi/winlayout.hxx
@@ -54,7 +54,9 @@ public:
/// Draw to the provided HDC.
virtual void DrawTextImpl(HDC hDC) const = 0;
-protected:
+ virtual bool CacheGlyphs(SalGraphics& rGraphics) const = 0;
+ virtual bool DrawCachedGlyphs(SalGraphics& rGraphics) const = 0;
+
HDC mhDC; // WIN32 device handle
HFONT mhFont; // WIN32 font handle
int mnBaseAdv; // x-offset relative to Layout origin
@@ -73,6 +75,8 @@ public:
virtual bool LayoutText( ImplLayoutArgs& ) SAL_OVERRIDE;
virtual void AdjustLayout( ImplLayoutArgs& ) SAL_OVERRIDE;
virtual void DrawTextImpl(HDC hDC) const SAL_OVERRIDE;
+ virtual bool CacheGlyphs(SalGraphics& rGraphics) const SAL_OVERRIDE;
+ virtual bool DrawCachedGlyphs(SalGraphics& rGraphics) const SAL_OVERRIDE;
virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&,
DeviceCoordinate* pGlyphAdvances, int* pCharPosAry,
const PhysicalFontFace** pFallbackFonts = NULL ) const SAL_OVERRIDE;
@@ -160,6 +164,8 @@ public:
virtual bool LayoutText( ImplLayoutArgs& ) SAL_OVERRIDE; // first step of layout
virtual void AdjustLayout( ImplLayoutArgs& ) SAL_OVERRIDE; // adjusting after fallback etc.
virtual void DrawTextImpl(HDC hDC) const SAL_OVERRIDE;
+ virtual bool CacheGlyphs(SalGraphics& rGraphics) const SAL_OVERRIDE;
+ virtual bool DrawCachedGlyphs(SalGraphics& rGraphics) const SAL_OVERRIDE;
// methods using string indexing
virtual sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra=0, int nFactor=1) const SAL_OVERRIDE;
More information about the Libreoffice-commits
mailing list