diff options
author | Simon Hausmann <shausman@rhea.troll.no> | 2007-02-21 11:31:33 +0100 |
---|---|---|
committer | Simon Hausmann <shausman@rhea.troll.no> | 2007-03-28 12:52:33 +0200 |
commit | 67cfdcc293944f4ace1815b7f7ca233ba87bf538 (patch) | |
tree | 112d773826c3fc6ab936fce7887242b707ae3c01 /src | |
parent | 7084be39cd8c6423876631f4d318f6162fa8efdc (diff) |
Ported the heuristic combining mark positioning
Diffstat (limited to 'src')
-rw-r--r-- | src/harfbuzz-global.h | 2 | ||||
-rw-r--r-- | src/harfbuzz-shaper.cpp | 159 | ||||
-rw-r--r-- | src/harfbuzz-shaper.h | 14 |
3 files changed, 104 insertions, 71 deletions
diff --git a/src/harfbuzz-global.h b/src/harfbuzz-global.h index d1f1b05..89dd1b0 100644 --- a/src/harfbuzz-global.h +++ b/src/harfbuzz-global.h @@ -39,6 +39,8 @@ typedef uint32_t HB_UChar32; typedef uint32_t HB_Glyph; typedef int32_t HB_Fixed; /* 26.6 */ +#define HB_FIXED_CONSTANT(v) ((v) * 64) + typedef int32_t HB_16Dot16; /* 16.16 */ typedef void * HB_Pointer; diff --git a/src/harfbuzz-shaper.cpp b/src/harfbuzz-shaper.cpp index aa8176c..aabbb3d 100644 --- a/src/harfbuzz-shaper.cpp +++ b/src/harfbuzz-shaper.cpp @@ -16,6 +16,9 @@ #include <assert.h> #include <stdio.h> +#define HB_MIN(a, b) ((a) < (b) ? (a) : (b)) +#define HB_MAX(a, b) ((a) > (b) ? (a) : (b)) + // ----------------------------------------------------------------------------------------------------- // // The line break algorithm. See http://www.unicode.org/reports/tr14/tr14-13.html @@ -205,45 +208,50 @@ static void calcLineBreaks(const HB_UChar16 *uc, uint32_t len, HB_CharAttributes // // -------------------------------------------------------------------------------------------------------------------------------------------- -static inline void positionCluster(HB_ShaperItem * /*item*/, int /*gfrom*/, int /*glast*/) +static inline void positionCluster(HB_ShaperItem *item, int gfrom, int glast) { -#if 0 int nmarks = glast - gfrom; assert(nmarks > 0); - QGlyphLayout *glyphs = item->glyphs; - QFontEngine *f = item->font; + HB_Glyph *glyphs = item->glyphs; + HB_GlyphAttributes *attributes = item->attributes; - glyph_metrics_t baseInfo = f->boundingBox(glyphs[gfrom].glyph); + HB_GlyphMetrics baseMetrics; + item->font->klass->getGlyphMetrics(item->font, glyphs[gfrom], &baseMetrics); - if (item->script == QUnicodeTables::Hebrew) + if (item->item.script == HB_Script_Hebrew + && (-baseMetrics.y) > baseMetrics.height) // we need to attach below the baseline, because of the hebrew iud. - baseInfo.height = qMax(baseInfo.height, -baseInfo.y); - - QRectF baseRect(baseInfo.x.toReal(), baseInfo.y.toReal(), baseInfo.width.toReal(), baseInfo.height.toReal()); + baseMetrics.height = -baseMetrics.y; // qDebug("---> positionCluster: cluster from %d to %d", gfrom, glast); // qDebug("baseInfo: %f/%f (%f/%f) off=%f/%f", baseInfo.x, baseInfo.y, baseInfo.width, baseInfo.height, baseInfo.xoff, baseInfo.yoff); - qreal size = (f->ascent()/10).toReal(); - qreal offsetBase = (size - 4) / 4 + qMin<qreal>(size, 4) + 1; + HB_Fixed size = item->font->klass->getAscent(item->font) / 10; + HB_Fixed offsetBase = HB_FIXED_CONSTANT(1) + (size - HB_FIXED_CONSTANT(4)) / 4; + if (size > HB_FIXED_CONSTANT(4)) + offsetBase += HB_FIXED_CONSTANT(4); + else + offsetBase += size; + //qreal offsetBase = (size - 4) / 4 + qMin<qreal>(size, 4) + 1; // qDebug("offset = %f", offsetBase); - bool rightToLeft = item->flags & QTextEngine::RightToLeft; + bool rightToLeft = item->item.bidiLevel % 2; int i; unsigned char lastCmb = 0; - QRectF attachmentRect; + HB_GlyphMetrics attachmentRect; for(i = 1; i <= nmarks; i++) { - glyph_t mark = glyphs[gfrom+i].glyph; - QPointF p; - glyph_metrics_t markInfo = f->boundingBox(mark); - QRectF markRect(markInfo.x.toReal(), markInfo.y.toReal(), markInfo.width.toReal(), markInfo.height.toReal()); + HB_Glyph mark = glyphs[gfrom+i]; + HB_GlyphMetrics markMetrics; + item->font->klass->getGlyphMetrics(item->font, mark, &markMetrics); + HB_FixedPoint p; + p.x = p.y = 0; // qDebug("markInfo: %f/%f (%f/%f) off=%f/%f", markInfo.x, markInfo.y, markInfo.width, markInfo.height, markInfo.xoff, markInfo.yoff); - qreal offset = offsetBase; - unsigned char cmb = glyphs[gfrom+i].attributes.combiningClass; + HB_Fixed offset = offsetBase; + unsigned char cmb = attributes[gfrom+i].combiningClass; // ### maybe the whole position determination should move down to heuristicSetGlyphAttributes. Would save some // bits in the glyphAttributes structure. @@ -260,19 +268,19 @@ static inline void positionCluster(HB_ShaperItem * /*item*/, int /*gfrom*/, int if ((cmb >= 10 && cmb <= 18) || cmb == 20 || cmb == 22 || cmb == 29 || cmb == 32) - cmb = QChar::Combining_Below; + cmb = HB_Combining_Below; // above else if (cmb == 23 || cmb == 27 || cmb == 28 || cmb == 30 || cmb == 31 || (cmb >= 33 && cmb <= 36)) - cmb = QChar::Combining_Above; + cmb = HB_Combining_Above; //below-right else if (cmb == 9 || cmb == 103 || cmb == 118) - cmb = QChar::Combining_BelowRight; + cmb = HB_Combining_BelowRight; // above-right else if (cmb == 24 || cmb == 107 || cmb == 122) - cmb = QChar::Combining_AboveRight; + cmb = HB_Combining_AboveRight; else if (cmb == 25) - cmb = QChar::Combining_AboveLeft; + cmb = HB_Combining_AboveLeft; // fixed: // 19 21 @@ -281,73 +289,88 @@ static inline void positionCluster(HB_ShaperItem * /*item*/, int /*gfrom*/, int // combining marks of different class don't interact. Reset the rectangle. if (cmb != lastCmb) { //qDebug("resetting rect"); - attachmentRect = baseRect; + attachmentRect = baseMetrics; } switch(cmb) { - case QChar::Combining_DoubleBelow: + case HB_Combining_DoubleBelow: // ### wrong in rtl context! - case QChar::Combining_BelowLeft: - p += QPointF(0, offset); - case QChar::Combining_BelowLeftAttached: - p += attachmentRect.bottomLeft() - markRect.topLeft(); + case HB_Combining_BelowLeft: + p.y += offset; + case HB_Combining_BelowLeftAttached: + p.x += attachmentRect.x - markMetrics.x; + p.y += (attachmentRect.y + attachmentRect.height) - markMetrics.y; break; - case QChar::Combining_Below: - p += QPointF(0, offset); - case QChar::Combining_BelowAttached: - p += attachmentRect.bottomLeft() - markRect.topLeft(); - p += QPointF((attachmentRect.width() - markRect.width())/2 , 0); + case HB_Combining_Below: + p.y += offset; + case HB_Combining_BelowAttached: + p.x += attachmentRect.x - markMetrics.x; + p.y += (attachmentRect.y + attachmentRect.height) - markMetrics.y; + + p.x += (attachmentRect.width - markMetrics.width) / 2; break; - case QChar::Combining_BelowRight: - p += QPointF(0, offset); - case QChar::Combining_BelowRightAttached: - p += attachmentRect.bottomRight() - markRect.topRight(); + case HB_Combining_BelowRight: + p.y += offset; + case HB_Combining_BelowRightAttached: + p.x += attachmentRect.x + attachmentRect.width - markMetrics.width - markMetrics.x; + p.y += attachmentRect.y + attachmentRect.height - markMetrics.y; break; - case QChar::Combining_Left: - p += QPointF(-offset, 0); - case QChar::Combining_LeftAttached: + case HB_Combining_Left: + p.x -= offset; + case HB_Combining_LeftAttached: break; - case QChar::Combining_Right: - p += QPointF(offset, 0); - case QChar::Combining_RightAttached: + case HB_Combining_Right: + p.x += offset; + case HB_Combining_RightAttached: break; - case QChar::Combining_DoubleAbove: + case HB_Combining_DoubleAbove: // ### wrong in RTL context! - case QChar::Combining_AboveLeft: - p += QPointF(0, -offset); - case QChar::Combining_AboveLeftAttached: - p += attachmentRect.topLeft() - markRect.bottomLeft(); + case HB_Combining_AboveLeft: + p.y -= offset; + case HB_Combining_AboveLeftAttached: + p.x += attachmentRect.x - markMetrics.x; + p.y += attachmentRect.y - markMetrics.y - markMetrics.height; break; - case QChar::Combining_Above: - p += QPointF(0, -offset); - case QChar::Combining_AboveAttached: - p += attachmentRect.topLeft() - markRect.bottomLeft(); - p += QPointF((attachmentRect.width() - markRect.width())/2 , 0); + case HB_Combining_Above: + p.y -= offset; + case HB_Combining_AboveAttached: + p.x += attachmentRect.x - markMetrics.x; + p.y += attachmentRect.y - markMetrics.y - markMetrics.height; + + p.x += (attachmentRect.width - markMetrics.width) / 2; break; - case QChar::Combining_AboveRight: - p += QPointF(0, -offset); - case QChar::Combining_AboveRightAttached: - p += attachmentRect.topRight() - markRect.bottomRight(); + case HB_Combining_AboveRight: + p.y -= offset; + case HB_Combining_AboveRightAttached: + p.x += attachmentRect.x + attachmentRect.width - markMetrics.x - markMetrics.width; + p.y += attachmentRect.y - markMetrics.y - markMetrics.height; break; - case QChar::Combining_IotaSubscript: + case HB_Combining_IotaSubscript: default: break; } // qDebug("char=%x combiningClass = %d offset=%f/%f", mark, cmb, p.x(), p.y()); - markRect.translate(p.x(), p.y()); - attachmentRect |= markRect; + markMetrics.x += p.x; + markMetrics.y += p.y; + + HB_GlyphMetrics unitedAttachmentRect = attachmentRect; + unitedAttachmentRect.x = HB_MIN(attachmentRect.x, markMetrics.x); + unitedAttachmentRect.y = HB_MIN(attachmentRect.y, markMetrics.y); + unitedAttachmentRect.width = HB_MAX(attachmentRect.x + attachmentRect.width, markMetrics.x + markMetrics.width) - unitedAttachmentRect.x; + unitedAttachmentRect.height = HB_MAX(attachmentRect.y + attachmentRect.height, markMetrics.y + markMetrics.height) - unitedAttachmentRect.y; + attachmentRect = unitedAttachmentRect; + lastCmb = cmb; if (rightToLeft) { - glyphs[gfrom+i].offset.x = QFixed::fromReal(p.x()); - glyphs[gfrom+i].offset.y = QFixed::fromReal(p.y()); + item->offsets[gfrom+i].x = p.x; + item->offsets[gfrom+i].y = p.y; } else { - glyphs[gfrom+i].offset.x = QFixed::fromReal(p.x()) - baseInfo.xoff; - glyphs[gfrom+i].offset.y = QFixed::fromReal(p.y()) - baseInfo.yoff; + item->offsets[gfrom+i].x = p.x - baseMetrics.xOffset; + item->offsets[gfrom+i].y = p.y - baseMetrics.yOffset; } - glyphs[gfrom+i].advance = QFixedPoint(); + item->advances[gfrom+i] = 0; } -#endif } void HB_HeuristicPosition(HB_ShaperItem *item) diff --git a/src/harfbuzz-shaper.h b/src/harfbuzz-shaper.h index 3c8886a..55808ac 100644 --- a/src/harfbuzz-shaper.h +++ b/src/harfbuzz-shaper.h @@ -175,12 +175,20 @@ HB_Face HB_NewFace(HB_Font font); void HB_FreeFace(HB_Face face); typedef struct { - HB_Bool (*stringToGlyphs)(HB_Font font, const HB_UChar16 *string, uint32_t length, HB_Glyph *glyphs, uint32_t *numGlyphs, HB_Bool rightToLeft); - void (*getAdvances)(HB_Font font, const HB_Glyph *glyphs, int numGlyphs, HB_Fixed *advances, int flags /*HB_ShaperFlag*/); - HB_Bool (*canRender)(HB_Font font, const HB_UChar16 *string, uint32_t length); + HB_Fixed x, y; + HB_Fixed width, height; + HB_Fixed xOffset, yOffset; +} HB_GlyphMetrics; + +typedef struct { + HB_Bool (*stringToGlyphs)(HB_Font font, const HB_UChar16 *string, uint32_t length, HB_Glyph *glyphs, uint32_t *numGlyphs, HB_Bool rightToLeft); + void (*getAdvances)(HB_Font font, const HB_Glyph *glyphs, int numGlyphs, HB_Fixed *advances, int flags /*HB_ShaperFlag*/); + HB_Bool (*canRender)(HB_Font font, const HB_UChar16 *string, uint32_t length); HB_Error (*getSFntTable)(HB_Font font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length); /* implementation needs to make sure to load a scaled glyph, so /no/ FT_LOAD_NO_SCALE */ HB_Error (*getPointInOutline)(HB_Font font, HB_Glyph glyph, int flags /*HB_ShaperFlag*/, uint32_t point, HB_Fixed *xpos, HB_Fixed *ypos, uint32_t *nPoints); + void (*getGlyphMetrics)(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics); + HB_Fixed (*getAscent)(HB_Font font); } HB_FontClass; typedef struct HB_Font_ { |