vcl/inc/CommonSalLayout.hxx |    1 
 vcl/inc/win/winlayout.hxx   |    4 ++
 vcl/win/gdi/salfont.cxx     |    2 -
 vcl/win/gdi/winlayout.cxx   |   85 +++++++++++++++++++++++++++++++-------------
 4 files changed, 67 insertions(+), 25 deletions(-)

New commits:
commit 3d456dfa6637c6c3ebe7a21f1f1a5b05039cee2a
Author: Khaled Hosny <khaledho...@eglug.org>
Date:   Fri Oct 28 04:19:46 2016 +0200

    tdf#98879: Fix vertical text on Windows for the new layout
    
    The DirectWrite rendering code wasn’t handling vertical text correctly
    at least when used with CommonSalLayout. It has been fixed and now made
    the default.
    
    We are also doing all vertical text handling on our own, so loading
    special vertical fonts on Windows is now disabled.
    
    Change-Id: I10d150367fe59c77459bb1b813b6f31a0ff0c5d0
    Reviewed-on: https://gerrit.libreoffice.org/30346
    Reviewed-by: Khaled Hosny <khaledho...@eglug.org>
    Tested-by: Khaled Hosny <khaledho...@eglug.org>

diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx
index 0dd44b2..86fe5d0 100644
--- a/vcl/inc/CommonSalLayout.hxx
+++ b/vcl/inc/CommonSalLayout.hxx
@@ -56,6 +56,7 @@ class CommonSalLayout : public GenericSalLayout
 public:
 #if defined(_WIN32)
     explicit                CommonSalLayout(HDC, WinFontInstance&, const 
WinFontFace&);
+    const FontSelectPattern& getFontSelData() const { return mrFontSelData; };
 #elif defined(MACOSX) || defined(IOS)
     explicit                CommonSalLayout(const CoreTextStyle&);
     const CoreTextStyle&    getFontData() const { return mrCoreTextStyle; };
diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx
index 1f04251..b137a4b 100755
--- a/vcl/inc/win/winlayout.hxx
+++ b/vcl/inc/win/winlayout.hxx
@@ -455,11 +455,15 @@ class D2DWriteTextOutRenderer : public TextOutRenderer
     typedef HRESULT(WINAPI *pD2D1CreateFactory_t)(D2D1_FACTORY_TYPE,
         REFIID, const D2D1_FACTORY_OPTIONS *, void **);
 
+    typedef HRESULT(WINAPI *pD2D1MakeRotateMatrix_t)(float, D2D1_POINT_2F,
+        D2D1_MATRIX_3X2_F*);
+
     typedef HRESULT(WINAPI *pDWriteCreateFactory_t)(DWRITE_FACTORY_TYPE,
         REFIID, IUnknown **);
 
     static HINSTANCE mmD2d1, mmDWrite;
     static pD2D1CreateFactory_t     D2D1CreateFactory;
+    static pD2D1MakeRotateMatrix_t  D2D1MakeRotateMatrix;
     static pDWriteCreateFactory_t   DWriteCreateFactory;
 
 public:
diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index d3e4e5e..b434184 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -1219,7 +1219,7 @@ void ImplGetLogFontFromFontSelect( HDC hDC,
         rLogFont.lfQuality = NONANTIALIASED_QUALITY;
 
     // select vertical mode if requested and available
-    if( pFont->mbVertical && nNameLen )
+    if (!SalLayout::UseCommonLayout() && pFont->mbVertical && nNameLen )
     {
         // vertical fonts start with an '@'
         memmove( &rLogFont.lfFaceName[1], &rLogFont.lfFaceName[0],
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index d82f86d..83db103 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -3339,6 +3339,7 @@ sal_GlyphId GraphiteLayoutWinImpl::getKashidaGlyph(int & 
rWidth)
 HINSTANCE D2DWriteTextOutRenderer::mmD2d1 = nullptr,
           D2DWriteTextOutRenderer::mmDWrite = nullptr;
 D2DWriteTextOutRenderer::pD2D1CreateFactory_t 
D2DWriteTextOutRenderer::D2D1CreateFactory = nullptr;
+D2DWriteTextOutRenderer::pD2D1MakeRotateMatrix_t 
D2DWriteTextOutRenderer::D2D1MakeRotateMatrix = nullptr;
 D2DWriteTextOutRenderer::pDWriteCreateFactory_t 
D2DWriteTextOutRenderer::DWriteCreateFactory = nullptr;
 
 bool D2DWriteTextOutRenderer::InitModules()
@@ -3348,10 +3349,11 @@ bool D2DWriteTextOutRenderer::InitModules()
     if (mmD2d1 && mmDWrite)
     {
         D2D1CreateFactory = pD2D1CreateFactory_t(GetProcAddress(mmD2d1, 
"D2D1CreateFactory"));
+        D2D1MakeRotateMatrix = pD2D1MakeRotateMatrix_t(GetProcAddress(mmD2d1, 
"D2D1MakeRotateMatrix"));
         DWriteCreateFactory = pDWriteCreateFactory_t(GetProcAddress(mmDWrite, 
"DWriteCreateFactory"));
     }
 
-    if (!D2D1CreateFactory || !DWriteCreateFactory)
+    if (!D2D1CreateFactory || !DWriteCreateFactory || !D2D1MakeRotateMatrix)
     {
         CleanupModules();
         return false;
@@ -3370,6 +3372,7 @@ void D2DWriteTextOutRenderer::CleanupModules()
     mmD2d1 = nullptr;
     mmDWrite = nullptr;
     D2D1CreateFactory = nullptr;
+    D2D1MakeRotateMatrix = nullptr;
     DWriteCreateFactory = nullptr;
 }
 #endif // ENABLE_GRAPHITE_DWRITE
@@ -3479,7 +3482,24 @@ bool D2DWriteTextOutRenderer::operator ()(SalLayout 
const &rLayout, HDC hDC,
         FLOAT  glyphAdvances[MAX_GLYPHS];
         DWRITE_GLYPH_OFFSET glyphOffsets[MAX_GLYPHS] = { { 0.0f, 0.0f }, };
 
+        bool bVertical = false;
+        double nYDiff = 0.0f;
+        const CommonSalLayout* pCSL = dynamic_cast<const 
CommonSalLayout*>(&rLayout);
+        if (pCSL)
+            bVertical = pCSL->getFontSelData().mbVertical;
+
+        if (bVertical)
+        {
+            DWRITE_FONT_METRICS aFM;
+            mpFontFace->GetMetrics(&aFM);
+            nYDiff = (aFM.ascent - aFM.descent) * mlfEmHeight / 
aFM.designUnitsPerEm;
+        }
+
         mpRT->BeginDraw();
+
+        D2D1_MATRIX_3X2_F aOrigTrans, aRotTrans;
+        mpRT->GetTransform(&aOrigTrans);
+
         do
         {
             nGlyphs = rLayout.GetNextGlyphs(1, glyphIntStr, *pPos, 
*pGetNextGlypInfo, glyphIntAdv);
@@ -3501,7 +3521,17 @@ bool D2DWriteTextOutRenderer::operator ()(SalLayout 
const &rLayout, HDC hDC,
                 0
             };
 
-            mpRT->DrawGlyphRun(baseline, &glyphs, pBrush);
+            if (bVertical && (glyphIntStr[0] & GF_ROTMASK) != GF_ROTL)
+            {
+                D2D1MakeRotateMatrix(90.0f, baseline, &aRotTrans);
+                mpRT->SetTransform(aOrigTrans * aRotTrans);
+                mpRT->DrawGlyphRun(baseline, &glyphs, pBrush);
+                mpRT->SetTransform(aOrigTrans);
+            }
+            else
+            {
+                mpRT->DrawGlyphRun({ baseline.x, baseline.y + nYDiff }, 
&glyphs, pBrush);
+            }
         } while (!pRectToErase);
 
         hr = mpRT->EndDraw();
@@ -3641,21 +3671,45 @@ bool 
D2DWriteTextOutRenderer::GetDWriteInkBox(IDWriteFontFace & rFontFace, SalLa
     Point aPos;
     sal_GlyphId nLGlyph;
     std::vector<uint16_t> indices;
+    std::vector<sal_GlyphId> gids;
     std::vector<Point>  positions;
     int nStart = 0;
     while (rLayout.GetNextGlyphs(1, &nLGlyph, aPos, nStart) == 1)
     {
         positions.push_back(aPos);
         indices.push_back(nLGlyph);
+        gids.push_back(nLGlyph);
     }
 
     auto aBoxes = GetGlyphInkBoxes(indices.data(), indices.data() + 
indices.size());
     if (aBoxes.empty())
         return false;
 
+    bool bVertical = false;
+    double nYDiff = 0.0f;
+    const CommonSalLayout* pCSL = dynamic_cast<const 
CommonSalLayout*>(&rLayout);
+    if (pCSL)
+        bVertical = pCSL->getFontSelData().mbVertical;
+
+    if (bVertical)
+    {
+        DWRITE_FONT_METRICS aFM;
+        rFontFace.GetMetrics(&aFM);
+        nYDiff = (aFM.ascent - aFM.descent) * mlfEmHeight / 
aFM.designUnitsPerEm;
+    }
+
     auto p = positions.begin();
+    auto gid = gids.begin();
     for (auto &b:aBoxes)
     {
+        if (bVertical)
+        {
+            if ((*gid++ & GF_ROTMASK) != GF_ROTL)
+                // FIXME: Hack, should rotate the box here instead.
+                b.expand(std::max(b.getHeight(), b.getWidth()));
+            else
+                b += Point(0, nYDiff);
+        }
         b += *p++;
         rOut.Union(b);
     }
@@ -4006,28 +4060,11 @@ LogicalFontInstance* WinFontFace::CreateFontInstance( 
FontSelectPattern& rFSD )
 
 void WinSalGraphics::DrawTextLayout(const CommonSalLayout& rLayout, HDC hDC)
 {
-    if (getenv("SAL_DWRITE_COMMON_LAYOUT"))
-    {
-        Point aPos(0, 0);
-        int nGlyphCount(0);
-        TextOutRenderer &render = TextOutRenderer::get();
-        bool result = render(rLayout, hDC, nullptr, &aPos, &nGlyphCount);
-        assert(!result);
-    }
-    else
-    {
-        Point aPos;
-        sal_GlyphId aGlyphId;
-        int nFetchedGlyphs = 0;
-        UINT oldTa = GetTextAlign(hDC);
-        SetTextAlign(hDC, (oldTa & ~TA_NOUPDATECP));
-        while (rLayout.GetNextGlyphs(1, &aGlyphId, aPos, nFetchedGlyphs))
-        {
-            ExtTextOutW(hDC, aPos.X(), aPos.Y(), ETO_GLYPH_INDEX, nullptr, 
reinterpret_cast<LPCWSTR>(&aGlyphId),
-                         1, nullptr);
-        }
-        SetTextAlign(hDC, oldTa);
-    }
+    Point aPos(0, 0);
+    int nGlyphCount(0);
+    TextOutRenderer &render = TextOutRenderer::get();
+    bool result = render(rLayout, hDC, nullptr, &aPos, &nGlyphCount);
+    assert(!result);
 }
 
 void WinSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout)
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to