Italic synthesize for circular layout. 81/203381/2
authorVictor Cebollada <v.cebollada@samsung.com>
Mon, 11 Mar 2019 11:12:42 +0000 (11:12 +0000)
committerVictor Cebollada <v.cebollada@samsung.com>
Tue, 16 Apr 2019 13:06:04 +0000 (14:06 +0100)
* Italic synthesization for circular layout was missing.
* Hint flag added to the cairo renderer pipeline.

Change-Id: Ic0bfe41b9419cca9483fd74a7e65f859cef08a69
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
dali/devel-api/text-abstraction/text-renderer-layout-helper.cpp
dali/devel-api/text-abstraction/text-renderer-layout-helper.h
dali/internal/text/text-abstraction/cairo-renderer.cpp

index b5a3eb4..5e17f9f 100755 (executable)
 // EXTERNAL INCLUDES
 #include <cmath>
 
+// INTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/font-client.h>
+
 namespace Dali
 {
 
 namespace TextAbstraction
 {
 
-void TransformToArcClockwise( const CircularTextParameters& parameters, double& x, double& y )
+void TransformToArc( const CircularTextParameters& parameters, double& x, double& y )
 {
-  double radius = parameters.radius;
-  double angle = parameters.beginAngle;
+  double yP = y;
 
-  angle -= parameters.invRadius * x;
+  // Does the italic synthesization for circular layout.
+  if( parameters.synthesizeItalic )
+  {
+    const double xP = -yP * sin( TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE );
+    yP *= cos( TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE );
 
-  radius -= y;
-  x =  radius * cos( angle );
-  y = -radius * sin( angle );
-
-  x += parameters.centerX;
-  y += parameters.centerY;
-}
+    x += xP;
+  }
 
-void TransformToArcAntiClockwise( const CircularTextParameters& parameters, double& x, double& y )
-{
+  double angle = 0.0;
   double radius = parameters.radius;
-  double angle = parameters.beginAngle;
 
-  angle += parameters.invRadius * x;
+  // Transform to a circular layout.
+  if( parameters.isClockwise )
+  {
+    angle = parameters.beginAngle - parameters.invRadius * x;
+    radius -= yP;
+
+    x = radius * cos( angle );
+    y = -radius * sin( angle );
+  }
+  else
+  {
+    angle = parameters.beginAngle + parameters.invRadius * x;
+    radius += yP;
 
-  radius += y;
-  x = radius * cos( angle );
-  y = radius * sin( -angle );
+    x = radius * cos( angle );
+    y = radius * sin( -angle );
+  }
 
+  // Transforms to the text area coordinate system.
   x += parameters.centerX;
   y += parameters.centerY;
 }
index 95921a1..a502967 100755 (executable)
@@ -39,34 +39,27 @@ struct DALI_ADAPTOR_API CircularTextParameters
     radius{ 0.0 },
     invRadius{ 0.0 },
     beginAngle{ 0.0 },
-    isClockwise{ true }
+    isClockwise{ true },
+    synthesizeItalic{ false }
   {}
 
-  double centerX;     ///< The 'x' center of the circular path.
-  double centerY;     ///< The 'y' center of the circular path.
-  double radius;      ///< The radius in pixels.
-  double invRadius;   ///< 1.0 / radius.
-  double beginAngle;  ///< The angle in radians where the circular text begins.
-  bool isClockwise:1; ///< Whether the circular text layout is clockwise.
+  double centerX;          ///< The 'x' center of the circular path.
+  double centerY;          ///< The 'y' center of the circular path.
+  double radius;           ///< The radius in pixels.
+  double invRadius;        ///< 1.0 / radius.
+  double beginAngle;       ///< The angle in radians where the circular text begins.
+  bool isClockwise:1;      ///< Whether the circular text layout is clockwise.
+  bool synthesizeItalic:1; ///< Whether to synthesize italic.
 };
 
 /**
- * @brief Transforms a vertex to wrap a clockwise circular path.
+ * @brief Transforms a vertex to wrap a circular path.
  *
  * @param[in] parameters The parameters of the circular path.
  * @param[in,out] x The 'x' coordinate of the vertex.
  * @param[in,out] y The 'y' coordinate of the vertex.
  */
-DALI_ADAPTOR_API void TransformToArcClockwise( const CircularTextParameters& parameters, double& x, double& y );
-
-/**
- * @brief Transforms a vertex to wrap an anti clockwise circular path.
- *
- * @param[in] parameters The parameters of the circular path.
- * @param[in,out] x The 'x' coordinate of the vertex.
- * @param[in,out] y The 'y' coordinate of the vertex.
- */
-DALI_ADAPTOR_API void TransformToArcAntiClockwise( const CircularTextParameters& parameters, double& x, double& y );
+DALI_ADAPTOR_API void TransformToArc( const CircularTextParameters& parameters, double& x, double& y );
 
 } // namespace TextAbstraction
 
index d65e1dd..18e0fcc 100755 (executable)
@@ -154,9 +154,6 @@ void WrapToCircularPath( cairo_t* cr, cairo_t* circularCr, const Dali::TextAbstr
   // Copy the path to get a cairo_path_t pointer used to iterate through all its items.
   std::unique_ptr<cairo_path_t, void(*)(cairo_path_t*)> path( cairo_copy_path( circularCr ), cairo_path_destroy );
 
-  void ( *transformToArc )( const Dali::TextAbstraction::CircularTextParameters&, double&, double& );
-  transformToArc = parameters.isClockwise ? &Dali::TextAbstraction::TransformToArcClockwise : &Dali::TextAbstraction::TransformToArcAntiClockwise;
-
   // Iterates through all the path items and transform each vertex to follow the circle.
   // Transformed vertices are added to a new path in the 'cr' context (the one used to render the circular text)
   for( int i = 0; i < path->num_data; i += path->data[i].header.length )
@@ -175,7 +172,7 @@ void WrapToCircularPath( cairo_t* cr, cairo_t* circularCr, const Dali::TextAbstr
         first = false;
         double x = data[1].point.x;
         double y = data[1].point.y;
-        transformToArc( parameters, x, y );
+        Dali::TextAbstraction::TransformToArc( parameters, x, y );
         cairo_move_to( cr, x, y );
         break;
       }
@@ -183,7 +180,7 @@ void WrapToCircularPath( cairo_t* cr, cairo_t* circularCr, const Dali::TextAbstr
       {
         double x = data[1].point.x;
         double y = data[1].point.y;
-        transformToArc( parameters, x, y );
+        Dali::TextAbstraction::TransformToArc( parameters, x, y );
         cairo_line_to( cr, x, y );
         break;
       }
@@ -195,9 +192,9 @@ void WrapToCircularPath( cairo_t* cr, cairo_t* circularCr, const Dali::TextAbstr
         double y2 = data[2].point.y;
         double x3 = data[3].point.x;
         double y3 = data[3].point.y;
-        transformToArc( parameters, x1, y1 );
-        transformToArc( parameters, x2, y2 );
-        transformToArc( parameters, x3, y3 );
+        Dali::TextAbstraction::TransformToArc( parameters, x1, y1 );
+        Dali::TextAbstraction::TransformToArc( parameters, x2, y2 );
+        Dali::TextAbstraction::TransformToArc( parameters, x3, y3 );
         cairo_curve_to( cr, x1, y1, x2, y2, x3, y3 );
         break;
       }
@@ -541,10 +538,7 @@ Devel::PixelBuffer RenderTextCairo( const TextAbstraction::TextRenderer::Paramet
             radians = fmod( radians, TWO_PI );
             radians += ( radians < 0.f ) ? TWO_PI : 0.f;
 
-            void ( *transformToArc )( const CircularTextParameters&, double&, double& );
-            transformToArc = circularTextParameters.isClockwise ? &TransformToArcClockwise : &TransformToArcAntiClockwise;
-
-            transformToArc( circularTextParameters, centerX, centerY );
+            TransformToArc( circularTextParameters, centerX, centerY );
 
             uint8_t* pixelsOut = nullptr;
             unsigned int widthOut = data.width;
@@ -788,7 +782,9 @@ Devel::PixelBuffer RenderTextCairo( const TextAbstraction::TextRenderer::Paramet
                              static_cast<double>( color.a ) );
 
       // Create the Cairo's font from the FreeType font.
-      std::unique_ptr<cairo_font_face_t, void(*)(cairo_font_face_t*)> fontFacePtr( cairo_ft_font_face_create_for_ft_face( run.fontFace, 0 ), cairo_font_face_destroy );
+      int options = 0;
+      options = CAIRO_HINT_STYLE_SLIGHT;
+      std::unique_ptr<cairo_font_face_t, void(*)(cairo_font_face_t*)> fontFacePtr( cairo_ft_font_face_create_for_ft_face( run.fontFace, options ), cairo_font_face_destroy );
       cairo_font_face_t* fontFace = fontFacePtr.get();
 
       static const cairo_user_data_key_t key = { 0 };
@@ -824,12 +820,21 @@ Devel::PixelBuffer RenderTextCairo( const TextAbstraction::TextRenderer::Paramet
       // Render the glyphs.
       if( isCircularText )
       {
-        // Create a new path where the text is laid out on a horizontal straight line.
-        cairo_new_path( circularCr );
-        cairo_move_to( circularCr, 0.0, 0.0 );
+        circularTextParameters.synthesizeItalic = synthesizeItalic;
+
+        const unsigned int glyphJump = circularTextParameters.synthesizeItalic ? 1u : run.numberOfGlyphs;
+
+        for( unsigned int index = 0u; index < run.numberOfGlyphs; index += glyphJump )
+        {
+          // Clears the current path where the text is laid out on a horizontal straight line.
+          cairo_new_path( circularCr );
+          cairo_move_to( circularCr, 0.0, 0.0 );
+
+          cairo_glyph_path( circularCr, ( cairoGlyphsBuffer + run.glyphIndex + index ), glyphJump );
 
-        cairo_glyph_path( circularCr, ( cairoGlyphsBuffer + run.glyphIndex ), run.numberOfGlyphs );
-        WrapToCircularPath( cr, circularCr, circularTextParameters );
+          WrapToCircularPath( cr, circularCr, circularTextParameters );
+          cairo_fill( cr );
+        }
       }
       else
       {
@@ -864,8 +869,9 @@ Devel::PixelBuffer RenderTextCairo( const TextAbstraction::TextRenderer::Paramet
           cairo_matrix_init_identity( &matrix );
           cairo_set_matrix( cr, &matrix );
         }
+
+        cairo_fill( cr );
       }
-      cairo_fill( cr );
     }
   }