aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/verttext.cpp23
-rw-r--r--src/core/SkFDot6.h3
-rw-r--r--src/ports/SkFontHost_FreeType.cpp133
-rw-r--r--src/ports/SkFontHost_FreeType_common.cpp72
4 files changed, 115 insertions, 116 deletions
diff --git a/gm/verttext.cpp b/gm/verttext.cpp
index 67a2da59c6..1471cbce9c 100644
--- a/gm/verttext.cpp
+++ b/gm/verttext.cpp
@@ -8,16 +8,32 @@
#include "gm.h"
#include "SkCanvas.h"
+#include "SkTypeface.h"
namespace skiagm {
#define TEXT_SIZE 48
static const char gText[] = "Hello";
+
+//Before shaping
+//static const char gText[] = "「テスト。」";
+//static const char gText[] = {0xE3,0x80,0x8C, 0xE3,0x83,0x86, 0xE3,0x82,0xB9, 0xE3,0x83,0x88, 0xE3,0x80,0x82, 0xE3,0x80,0x8D, 0x0};
+
+//After shaping
+//static const char gText[] = "﹁テスト︒﹂";
+//static const char gText[] = {0xEF,0xB9,0x81, 0xE3,0x83,0x86, 0xE3,0x82,0xB9, 0xE3,0x83,0x88, 0xEF,0xB8,0x92, 0xEF,0xB9,0x82, 0x0};
+
static const size_t gLen = sizeof(gText) - 1;
class VertTextGM : public GM {
public:
- VertTextGM() {}
+ VertTextGM()
+ // : fFace(SkTypeface::CreateFromName("unifont", SkTypeface::kNormal))
+ // : fFace(SkTypeface::CreateFromFile("MotoyaL04Mincho_3.ttf"))
+ {
+ }
+
+ //SkAutoTUnref<SkTypeface> fFace;
protected:
@@ -58,10 +74,11 @@ protected:
SkScalar y = SkIntToScalar(50);
for (int i = 0; i < 4; ++i) {
- SkPaint paint;
+ SkPaint paint;
paint.setAntiAlias(true);
paint.setTextSize(SkIntToScalar(TEXT_SIZE));
-
+ //paint.setTypeface(fFace);
+ //paint.setFakeBoldText(true);
paint.setVerticalText(false);
drawBaseline(canvas, paint, x, y);
diff --git a/src/core/SkFDot6.h b/src/core/SkFDot6.h
index aa588572f8..9b8e4d05ad 100644
--- a/src/core/SkFDot6.h
+++ b/src/core/SkFDot6.h
@@ -10,6 +10,7 @@
#ifndef SkFDot6_DEFINED
#define SkFDot6_DEFINED
+#include "SkScalar.h"
#include "SkMath.h"
typedef int32_t SkFDot6;
@@ -40,8 +41,10 @@ inline SkFixed SkFDot6ToFixed(SkFDot6 x) {
#ifdef SK_SCALAR_IS_FLOAT
#define SkScalarToFDot6(x) (SkFDot6)((x) * 64)
+ #define SkFDot6ToScalar(x) ((SkScalar)(x) * SkFloatToScalar(0.015625f))
#else
#define SkScalarToFDot6(x) ((x) >> 10)
+ #define SkFDot6ToScalar(x) ((x) << 10)
#endif
inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b) {
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index 0f3dded50c..4f036a81e8 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -830,6 +830,11 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
// See http://code.google.com/p/skia/issues/detail?id=222.
loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
+ // Use vertical layout if requested.
+ if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
+ loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
+ }
+
fLoadGlyphFlags = loadFlags;
fDoLinearMetrics = linearMetrics;
}
@@ -982,6 +987,20 @@ void SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph,
bbox->xMax = (bbox->xMax + 63) & ~63;
bbox->yMax = (bbox->yMax + 63) & ~63;
}
+
+ // Must come after snapToPixelBoundary so that the width and height are
+ // consistent. Otherwise asserts will fire later on when generating the
+ // glyph image.
+ if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
+ FT_Vector vector;
+ vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
+ vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
+ FT_Vector_Transform(&vector, &fMatrix22);
+ bbox->xMin += vector.x;
+ bbox->xMax += vector.x;
+ bbox->yMin += vector.y;
+ bbox->yMax += vector.y;
+ }
}
void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) {
@@ -1026,8 +1045,6 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
return;
}
- SkFixed vLeft = 0, vTop = 0;
-
switch ( fFace->glyph->format ) {
case FT_GLYPH_FORMAT_OUTLINE: {
FT_BBox bbox;
@@ -1046,15 +1063,10 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
getBBoxForCurrentGlyph(glyph, &bbox, true);
- glyph->fWidth = SkToU16((bbox.xMax - bbox.xMin) >> 6);
- glyph->fHeight = SkToU16((bbox.yMax - bbox.yMin) >> 6);
- glyph->fTop = -SkToS16(bbox.yMax >> 6);
- glyph->fLeft = SkToS16(bbox.xMin >> 6);
-
- if ((fRec.fFlags & SkScalerContext::kVertical_Flag)) {
- vLeft = SkFDot6ToFixed(bbox.xMin);
- vTop = SkFDot6ToFixed(bbox.yMax);
- }
+ glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin));
+ glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin));
+ glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax));
+ glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin));
updateGlyphIfLCD(glyph);
@@ -1066,6 +1078,16 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
FT_GlyphSlot_Own_Bitmap(fFace->glyph);
FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0);
}
+
+ if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
+ FT_Vector vector;
+ vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
+ vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
+ FT_Vector_Transform(&vector, &fMatrix22);
+ fFace->glyph->bitmap_left += SkFDot6Floor(vector.x);
+ fFace->glyph->bitmap_top += SkFDot6Floor(vector.y);
+ }
+
glyph->fWidth = SkToU16(fFace->glyph->bitmap.width);
glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows);
glyph->fTop = -SkToS16(fFace->glyph->bitmap_top);
@@ -1077,72 +1099,27 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
goto ERROR;
}
- if (fDoLinearMetrics) {
- glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance);
- glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance);
- } else {
- glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x);
- glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y);
-
- if (fRec.fFlags & kDevKernText_Flag) {
- glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta);
- glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta);
+ if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
+ if (fDoLinearMetrics) {
+ glyph->fAdvanceX = -SkFixedMul(fMatrix22.xy, fFace->glyph->linearVertAdvance);
+ glyph->fAdvanceY = SkFixedMul(fMatrix22.yy, fFace->glyph->linearVertAdvance);
+ } else {
+ glyph->fAdvanceX = -SkFDot6ToFixed(fFace->glyph->advance.x);
+ glyph->fAdvanceY = SkFDot6ToFixed(fFace->glyph->advance.y);
}
- }
-
- if ((fRec.fFlags & SkScalerContext::kVertical_Flag)
- && fFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
-
- //TODO: do we need to specially handle SubpixelPositioning and Kerning?
-
- FT_Matrix identityMatrix;
- identityMatrix.xx = identityMatrix.yy = SK_Fixed1;
- identityMatrix.xy = identityMatrix.yx = 0;
-
- // if the matrix is not the identity matrix then we need to re-load the
- // glyph with the identity matrix to get the necessary bounding box
- if (memcmp(&fMatrix22, &identityMatrix, sizeof(FT_Matrix)) != 0) {
-
- FT_Set_Transform(fFace, &identityMatrix, NULL);
-
- err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags );
- if (err != 0) {
- SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
- fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err));
- goto ERROR;
- }
+ } else {
+ if (fDoLinearMetrics) {
+ glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance);
+ glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance);
+ } else {
+ glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x);
+ glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y);
- if (fRec.fFlags & kEmbolden_Flag) {
- emboldenOutline(fFace, &fFace->glyph->outline);
+ if (fRec.fFlags & kDevKernText_Flag) {
+ glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta);
+ glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta);
}
}
-
- // bounding box of the unskewed and unscaled glyph
- FT_BBox bbox = {0, 0, 0, 0}; // Suppress Coverity warning.
- getBBoxForCurrentGlyph(glyph, &bbox);
-
- // compute the vertical gap above and below the glyph if the glyph were
- // centered within the linearVertAdvance
- SkFixed vGap = (fFace->glyph->linearVertAdvance - SkFDot6ToFixed(bbox.yMax - bbox.yMin)) / 2;
-
- // the origin point of the glyph when rendered vertically
- FT_Vector vOrigin;
- vOrigin.x = fFace->glyph->linearHoriAdvance / 2;
- vOrigin.y = vGap + SkFDot6ToFixed(bbox.yMax);
-
- // transform the vertical origin based on the matrix of the actual glyph
- FT_Vector_Transform(&vOrigin, &fMatrix22);
-
- // compute a new offset vector for the glyph by subtracting the vertical
- // origin from the original horizontal offset vector
- glyph->fLeft = SkFixedRoundToInt(vLeft - vOrigin.x);
- glyph->fTop = -SkFixedRoundToInt(vTop - vOrigin.y);
-
- updateGlyphPosIfLCD(glyph);
-
- // use the vertical advance values computed by freetype
- glyph->fAdvanceX = -SkFixedMul(fMatrix22.xy, fFace->glyph->linearVertAdvance);
- glyph->fAdvanceY = SkFixedMul(fMatrix22.yy, fFace->glyph->linearVertAdvance);
}
@@ -1200,6 +1177,16 @@ void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph,
}
generateGlyphPath(fFace, glyph, path);
+
+ // The path's origin from FreeType is always the horizontal layout origin.
+ // Offset the path so that it is relative to the vertical origin if needed.
+ if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
+ FT_Vector vector;
+ vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
+ vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
+ FT_Vector_Transform(&vector, &fMatrix22);
+ path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y));
+ }
}
void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
diff --git a/src/ports/SkFontHost_FreeType_common.cpp b/src/ports/SkFontHost_FreeType_common.cpp
index 332b8c47b8..3a827d70bc 100644
--- a/src/ports/SkFontHost_FreeType_common.cpp
+++ b/src/ports/SkFontHost_FreeType_common.cpp
@@ -119,46 +119,6 @@ static void copyFT2LCD16(const SkGlyph& glyph, const FT_Bitmap& bitmap,
}
}
-///////////////////////////////////////////////////////////////////////////////
-
-#define ft2sk(x) SkFixedToScalar(SkFDot6ToFixed(x))
-
-#if FREETYPE_MAJOR >= 2 && FREETYPE_MINOR >= 2
- #define CONST_PARAM const
-#else // older freetype doesn't use const here
- #define CONST_PARAM
-#endif
-
-static int move_proc(CONST_PARAM FT_Vector* pt, void* ctx) {
- SkPath* path = (SkPath*)ctx;
- path->close(); // to close the previous contour (if any)
- path->moveTo(ft2sk(pt->x), -ft2sk(pt->y));
- return 0;
-}
-
-static int line_proc(CONST_PARAM FT_Vector* pt, void* ctx) {
- SkPath* path = (SkPath*)ctx;
- path->lineTo(ft2sk(pt->x), -ft2sk(pt->y));
- return 0;
-}
-
-static int quad_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1,
- void* ctx) {
- SkPath* path = (SkPath*)ctx;
- path->quadTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x), -ft2sk(pt1->y));
- return 0;
-}
-
-static int cubic_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1,
- CONST_PARAM FT_Vector* pt2, void* ctx) {
- SkPath* path = (SkPath*)ctx;
- path->cubicTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x),
- -ft2sk(pt1->y), ft2sk(pt2->x), -ft2sk(pt2->y));
- return 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face,
const SkGlyph& glyph,
SkMaskGamma::PreBlend* maskPreBlend)
@@ -313,6 +273,38 @@ void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face,
#endif
}
+///////////////////////////////////////////////////////////////////////////////
+
+static int move_proc(const FT_Vector* pt, void* ctx) {
+ SkPath* path = (SkPath*)ctx;
+ path->close(); // to close the previous contour (if any)
+ path->moveTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
+ return 0;
+}
+
+static int line_proc(const FT_Vector* pt, void* ctx) {
+ SkPath* path = (SkPath*)ctx;
+ path->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
+ return 0;
+}
+
+static int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1,
+ void* ctx) {
+ SkPath* path = (SkPath*)ctx;
+ path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
+ SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y));
+ return 0;
+}
+
+static int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
+ const FT_Vector* pt2, void* ctx) {
+ SkPath* path = (SkPath*)ctx;
+ path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
+ SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y),
+ SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y));
+ return 0;
+}
+
void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face,
const SkGlyph& glyph,
SkPath* path)