[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    font handling bug in qt 4.0.1
From:       LiuCougar <liucougar () gmail ! com>
Date:       2005-09-26 3:22:31
Message-ID: 9558067805092520221223e3f2 () mail ! gmail ! com
[Download RAW message or body]

*Short description: Fake oblique font does not work properly

*What I did:
Open qtconfig, in the font tab, select a font which does not have an
italic style, select style oblique

*What I expected to see:
the "Sample Text" in the lineedit should be shown in style oblique

*What I got instead:
the "Sample Text" in the lineedit did not change style to oblique

Attached is a patch to solve this issue, and also add support for
"fake bold" as well (which is supported by freetype 2.1.10)

Please someone review it?

Regards,
Cougar
--
"People's characters are strengthened through struggle against
difficulties; they are weakened by comfort."
- Old Chinese adage

["oblique_bold.patch" (application/octet-stream)]

Index: src/gui/text/qfontengine_x11.cpp
===================================================================
--- src/gui/text/qfontengine_x11.cpp	(revision 463892)
+++ src/gui/text/qfontengine_x11.cpp	(working copy)
@@ -39,6 +39,10 @@
 #include "qfont_p.h"
 #include "qfontengine_p.h"
 #include "qopentype_p.h"
+#ifdef FT_SYNTHESIS_H
+#define HAVE_FT_GLYPHSLOT_EMBOLDEN 1
+#include FT_SYNTHESIS_H
+#endif
 #include <qhash.h>
 
 #include <private/qpainter_p.h>
@@ -547,6 +551,14 @@
     if (!antialias || subpixel == FC_RGBA_UNKNOWN)
         subpixel = FC_RGBA_NONE;
 
+#ifdef FC_EMBOLDEN
+    if (FcPatternGetBool (pattern,
+            FC_EMBOLDEN, 0, &b) != FcResultMatch)
+        b = FcFalse;
+
+    embolden = b;
+#endif
+
     if (!library)
         FT_Init_FreeType(&library);
 
@@ -720,11 +732,83 @@
 
     FT_GlyphSlot slot = face->glyph;
 
+#if HAVE_FT_GLYPHSLOT_EMBOLDEN
+    if (embolden && (face->style_flags & FT_STYLE_FLAG_BOLD) == 0) {
+        FT_GlyphSlot_Embolden (slot);
+    }
+#endif
+
     int left  = FLOOR(slot->metrics.horiBearingX);
     int right = CEIL(slot->metrics.horiBearingX + slot->metrics.width);
     int top    = CEIL(slot->metrics.horiBearingY);
     int bottom = FLOOR(slot->metrics.horiBearingY - slot->metrics.height);
 
+    FcMatrix * matrix_builtin = 0;
+    FcPatternGetMatrix( _pattern, FC_MATRIX, 0, &matrix_builtin );
+    if ( matrix_builtin ) {
+        FT_Matrix mat2;
+        mat2.xx = (FT_Fixed) (0x10000L * matrix_builtin->xx);
+        mat2.yy = (FT_Fixed) (0x10000L * matrix_builtin->yy);
+        mat2.yx = (FT_Fixed) (0x10000L * matrix_builtin->yx);
+        mat2.xy = (FT_Fixed) (0x10000L * matrix_builtin->xy);
+
+        FT_Outline_Transform(&slot->outline, &mat2);
+
+        FT_Vector       vector;
+
+        /* The matrix transformation may alter these four metrics attributes as well.
+         * As this is a const function, it is impossible to overwrite the attributes here,
+         * so they are commented out.
+         * Fortunately, in the most common cases (fake oblique), they are not modified.
+         */
+        /*
+        vector.x = 0;
+        vector.y = face->size->metrics.descender;
+        FT_Vector_Transform (&vector, &mat2);
+        std::cout << metrics.descender << " " <<vector.y << " metrics.descender\n";
+
+        vector.x = 0;
+        vector.y = face->size->metrics.ascender;
+        FT_Vector_Transform (&vector, &mat2);
+        std::cout << metrics.ascender<< " " <<vector.y << " metrics.ascender\n";
+
+        vector.x = 0;
+        vector.y = face->size->metrics.height;
+        FT_Vector_Transform (&vector, &mat2);
+        std::cout << metrics.height<< " " <<vector.y << " metrics.height\n";
+
+        //This is further dependent on FC_CHAR_WIDTH (see libXft)
+        vector.x = face->size->metrics.max_advance;
+        vector.y = 0;
+        FT_Vector_Transform (&vector, &mat2);
+        std::cout << metrics.max_advance << " " <<vector.x << " metrics.max_advance\n";
+        */
+
+        int xc, yc;
+        left = right = top = bottom = 0;
+        for(xc = 0; xc <= 1; xc ++) {
+            for(yc = 0; yc <= 1; yc++) {
+                vector.x = slot->metrics.horiBearingX + xc * slot->metrics.width;
+                vector.y = slot->metrics.horiBearingY - yc * slot->metrics.height;
+                FT_Vector_Transform(&vector, &mat2);
+                if(xc == 0 && yc == 0) {
+                    left = right = vector.x;
+                    top = bottom = vector.y;
+                } else {
+                    if(left > vector.x) left = vector.x;
+                    if(right < vector.x) right = vector.x;
+                    if(bottom > vector.y) bottom = vector.y;
+                    if(top < vector.y) top = vector.y;
+                }
+
+            }
+        }
+        left = FLOOR(left);
+        right = CEIL(right);
+        bottom = FLOOR(bottom);
+        top = CEIL(top);
+    }
+
 #ifndef QT_NO_XRENDER
     XGlyphInfo info;
 #else
@@ -1199,6 +1283,12 @@
             if (g->format != FT_GLYPH_FORMAT_OUTLINE)
                 continue;
 
+#if HAVE_FT_GLYPHSLOT_EMBOLDEN
+            if (embolden && (face->style_flags & FT_STYLE_FLAG_BOLD) == 0) {
+                FT_GlyphSlot_Embolden (g);
+            }
+#endif
+
             // convert the outline to a painter path
             int i = 0;
             for (int c = 0; c < g->outline.n_contours; ++c) {
Index: src/gui/text/qfontengine_x11_p.h
===================================================================
--- src/gui/text/qfontengine_x11_p.h	(revision 463892)
+++ src/gui/text/qfontengine_x11_p.h	(working copy)
@@ -193,6 +193,9 @@
     int ysize;
     bool antialias;
     bool outline_drawing;
+#ifdef FC_EMBOLDEN
+    bool embolden;
+#endif
     int subpixel;
 
 public:
Index: src/gui/text/qfontdatabase_x11.cpp
===================================================================
--- src/gui/text/qfontdatabase_x11.cpp	(revision 463892)
+++ src/gui/text/qfontdatabase_x11.cpp	(working copy)
@@ -1240,9 +1240,25 @@
 
                 QtFontStyle::Key key = style->key;
 
+                // does this style have a bold equivalent?
+                key.weight = QFont::Bold;
+                QtFontStyle *equiv = foundry->style(key);
+                if (!equiv) {
+                    // let's fake one...
+                    equiv = foundry->style(key, true);
+                    equiv->smoothScalable = true;
+
+                    QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true);
+                    QtFontEncoding *equiv_enc = equiv_size->encodingID(-1, 0, 0, 0, 0, true);
+
+                    // keep the same pitch
+                    equiv_enc->pitch = enc->pitch;
+		    key.weight = QFont::Normal;
+                }
+
                 // does this style have an italic equivalent?
                 key.style = QFont::StyleItalic;
-                QtFontStyle *equiv = foundry->style(key);
+                equiv = foundry->style(key);
                 if (equiv) continue;
 
                 // does this style have an oblique equivalent?
@@ -1421,7 +1437,6 @@
 
     FcResult result;
     FcFontSet *fs = FcFontSort(0, pattern, FcTrue, 0, &result);
-    FcPatternDestroy(pattern);
     if (!fs)
         return 0;
 
@@ -1501,6 +1516,14 @@
     } else {
         // create a multi engine for the fontset fontconfig gave us
         FcFontSet *fontSet = FcFontSetCreate();
+        // the original pattern should be added rather than the return
+        // value from FcFontSort, for addPatternProps can not add
+        // all necessary pattern props: such as the Matrix which is 
+        // essential for the fake oblique support and embold settings
+        // specified in fonts.conf
+        FcFontSetAdd(fontSet, pattern);
+        pattern = 0;
+#if 0
         for (int i = 0; i < fs->nfont; ++i) {
             FcPattern *pattern = FcPatternDuplicate(fs->fonts[i]);
             // add properties back in as the font selected from the
@@ -1508,11 +1531,14 @@
             addPatternProps(pattern, key, false, true, fp, request, script);
             FcFontSetAdd(fontSet, pattern);
         }
+#endif
 
         fe = new QFontEngineMultiFT(fontSet, fp->screen);
         fe->fontDef = request;
     }
 
+    if(pattern)
+        FcPatternDestroy(pattern);
     FcFontSetDestroy(fs);
     return fe;
 }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic