@@ -328,11 +328,34 @@ void shapeLines(Shaping& shaping,
328328    float  x = 0 ;
329329    float  y = 0 ;
330330    float  maxLineLength = 0 ;
331+     bool  hasBaseline{false };
332+ 
333+     for  (std::size_t  i = 0 ; i < lines.size (); ++i) {
334+         TaggedString& line = lines[i];
335+         line.trim ();
336+         for  (std::size_t  j = 0 ; j < line.length (); ++j) {
337+             const  std::size_t  sectionIndex = line.getSectionIndex (j);
338+             const  SectionOptions& section = line.sectionAt (sectionIndex);
339+             char16_t  codePoint = line.getCharCodeAt (i);
340+             auto  glyphs = glyphMap.find (section.fontStackHash );
341+             if  (glyphs == glyphMap.end ()) {
342+                 continue ;
343+             }
344+             auto  it = glyphs->second .find (codePoint);
345+             if  (it == glyphs->second .end () || !it->second ) {
346+                 continue ;
347+             }
348+             const  Glyph& glyph = **it->second ;
349+             hasBaseline = glyph.metrics .ascender  != 0  && glyph.metrics .descender  != 0 ;
350+             if  (!hasBaseline) break ;
351+         }
352+         if  (!hasBaseline) break ;
353+     }
331354
332355    const  float  justify = textJustify == style::TextJustifyType::Right ? 1  :
333356        textJustify == style::TextJustifyType::Left ? 0  :
334357        0.5 ;
335-      
358+ 
336359    for  (TaggedString& line : lines) {
337360        //  Collapse whitespace so it doesn't throw off justification
338361        line.trim ();
@@ -360,13 +383,17 @@ void shapeLines(Shaping& shaping,
360383
361384            const  Glyph& glyph = **it->second ;
362385
363-             //  Each glyph's baseline is starting from its acsender, which is the vertical distance
364-             //  from the horizontal baseline to the highest ‘character’ coordinate in a font face.
365-             //  Since we're laying out at 24 points, we need also calculate how much it will move
366-             //  when we scale up or down.
367-             const  bool  hasBaseline = glyph.metrics .ascender  != 0  && glyph.metrics .descender  != 0 ;
368-             const  double  baselineOffset = (hasBaseline ? (-glyph.metrics .ascender  * section.scale ) : shaping.yOffset ) +
369-                                           (lineMaxScale - section.scale ) * util::ONE_EM;
386+             //  In order to make different fonts aligned, they must share a general baseline that starts from the midline
387+             //  of each font face.  Baseline offset is the vertical distance from font face's baseline to its top most
388+             //  position, which is the half size of the sum (ascender + descender). Since glyph's position is counted
389+             //  from the top left corner, the negative shift is needed. So different fonts shares the same baseline but
390+             //  with different offset shift. If font's baseline is not applicable, fall back to use a default baseline
391+             //  offset, see shaping.yOffset. Since we're laying out at 24 points, we need also calculate how much it will
392+             //  move when we scale up or down.
393+             const  double  baselineOffset =
394+                 (hasBaseline ? ((-glyph.metrics .ascender  + glyph.metrics .descender ) / 2  * section.scale )
395+                              : shaping.yOffset ) +
396+                 (lineMaxScale - section.scale ) * util::ONE_EM;
370397
371398            if  (writingMode == WritingModeType::Horizontal ||
372399                //  Don't verticalize glyphs that have no upright orientation if vertical placement is disabled.
@@ -407,6 +434,7 @@ void shapeLines(Shaping& shaping,
407434    shaping.bottom  = shaping.top  + height;
408435    shaping.left  += -anchorAlign.horizontalAlign  * maxLineLength;
409436    shaping.right  = shaping.left  + maxLineLength;
437+     shaping.hasBaseline  = hasBaseline;
410438}
411439
412440const  Shaping getShaping (const  TaggedString& formattedString,
0 commit comments