aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ports
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-03-09 17:22:22 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-03-09 17:22:22 +0000
commit0bf64d48cc18d551dadc7cce0c990352e04f9af8 (patch)
tree628d88bbb60d4462c973dac4a05e9c9b16d40e38 /src/ports
parentea446b9bc594f9ca1cb894d5c3fa05358bfebba3 (diff)
implement fontmetrics
git-svn-id: http://skia.googlecode.com/svn/trunk@116 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/ports')
-rwxr-xr-xsrc/ports/SkFontHost_mac.cpp167
1 files changed, 134 insertions, 33 deletions
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 0f509f1e22..3513edc745 100755
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -17,6 +17,7 @@
#include <carbon/carbon.h>
#include "SkFontHost.h"
#include "SkDescriptor.h"
+#include "SkEndian.h"
#include "SkPoint.h"
// Give 1MB font cache budget
@@ -90,14 +91,13 @@ protected:
virtual void generateMetrics(SkGlyph* glyph);
virtual void generateImage(const SkGlyph& glyph);
virtual void generatePath(const SkGlyph& glyph, SkPath* path);
- virtual void generateLineHeight(SkPoint* ascent, SkPoint* descent);
virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);
-// virtual SkDeviceContext getDC() { return NULL; } // not implemented on Mac
private:
ATSUTextLayout fLayout;
ATSUStyle fStyle;
CGColorSpaceRef fGrayColorSpace;
+ CGAffineTransform fTransform;
static OSStatus MoveTo(const Float32Point *pt, void *cb);
static OSStatus Line(const Float32Point *pt, void *cb);
@@ -106,18 +106,31 @@ private:
};
SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc)
- : SkScalerContext(desc), fLayout(0), fStyle(0) {
+ : SkScalerContext(desc), fLayout(0), fStyle(0)
+{
SkAutoMutexAcquire ac(gFTMutex);
OSStatus err;
err = ::ATSUCreateStyle(&fStyle);
SkASSERT(0 == err);
-
- Fixed fixedSize = SkScalarToFixed(fRec.fTextSize);
- static const ATSUAttributeTag sizeTag = kATSUSizeTag;
- static const ByteCount sizeTagSize = sizeof(Fixed);
- const ATSUAttributeValuePtr values[] = { &fixedSize };
- err = ::ATSUSetAttributes(fStyle,1,&sizeTag,&sizeTagSize,values);
+
+ SkMatrix m;
+ fRec.getSingleMatrix(&m);
+
+ fTransform = CGAffineTransformMake(SkScalarToFloat(m[SkMatrix::kMScaleX]),
+ SkScalarToFloat(m[SkMatrix::kMSkewX]),
+ SkScalarToFloat(m[SkMatrix::kMSkewY]),
+ SkScalarToFloat(m[SkMatrix::kMScaleY]),
+ SkScalarToFloat(m[SkMatrix::kMTransX]),
+ SkScalarToFloat(m[SkMatrix::kMTransY]));
+
+
+ Fixed fixedSize = SK_Fixed1; //SkScalarToFixed(fRec.fTextSize);
+ static const ATSUAttributeTag tags[] = { kATSUSizeTag, kATSUFontMatrixTag };
+ static const ByteCount sizes[] = { sizeof(Fixed), sizeof(fTransform) };
+ const ATSUAttributeValuePtr values[] = { &fixedSize, &fTransform };
+ err = ::ATSUSetAttributes(fStyle, SK_ARRAY_COUNT(tags),
+ tags, sizes, values);
SkASSERT(0 == err);
err = ::ATSUCreateTextLayout(&fLayout);
@@ -188,21 +201,118 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
}
}
+static void convert_metrics(SkPaint::FontMetrics* dst,
+ const ATSFontMetrics& src) {
+ dst->fTop = -SkFloatToScalar(src.ascent);
+ dst->fAscent = -SkFloatToScalar(src.ascent);
+ dst->fDescent = SkFloatToScalar(src.descent);
+ dst->fBottom = SkFloatToScalar(src.descent);
+ dst->fLeading = SkFloatToScalar(src.leading);
+}
+
+static void* get_font_table(ATSFontRef fontID, uint32_t tag) {
+ ByteCount size;
+ OSStatus err = ATSFontGetTable(fontID, tag, 0, 0, NULL, &size);
+ if (err) {
+ return NULL;
+ }
+ void* data = sk_malloc_throw(size);
+ err = ATSFontGetTable(fontID, tag, 0, size, data, &size);
+ if (err) {
+ sk_free(data);
+ data = NULL;
+ }
+ return data;
+}
+
+static int get_be16(const void* data, size_t offset) {
+ const char* ptr = reinterpret_cast<const char*>(data);
+ uint16_t value = *reinterpret_cast<const uint16_t*>(ptr + offset);
+ int n = SkEndian_SwapBE16(value);
+ // now force it to be signed
+ return n << 16 >> 16;
+}
+
+#define SFNT_HEAD_UPEM_OFFSET 18
+#define SFNT_HEAD_YMIN_OFFSET 38
+#define SFNT_HEAD_YMAX_OFFSET 42
+#define SFNT_HEAD_STYLE_OFFSET 44
+
+#define SFNT_HHEA_ASCENT_OFFSET 4
+#define SFNT_HHEA_DESCENT_OFFSET 6
+#define SFNT_HHEA_LEADING_OFFSET 8
+
+static bool init_vertical_metrics(ATSFontRef font, SkPoint pts[5]) {
+ void* head = get_font_table(font, 'head');
+ if (NULL == head) {
+ return false;
+ }
+ void* hhea = get_font_table(font, 'hhea');
+ if (NULL == hhea) {
+ sk_free(head);
+ return false;
+ }
+
+ int upem = get_be16(head, SFNT_HEAD_UPEM_OFFSET);
+ int ys[5];
+
+ ys[0] = -get_be16(head, SFNT_HEAD_YMAX_OFFSET);
+ ys[1] = -get_be16(hhea, SFNT_HHEA_ASCENT_OFFSET);
+ ys[2] = -get_be16(hhea, SFNT_HHEA_DESCENT_OFFSET);
+ ys[3] = -get_be16(head, SFNT_HEAD_YMIN_OFFSET);
+ ys[4] = get_be16(hhea, SFNT_HHEA_LEADING_OFFSET);
+
+ // now do some cleanup, to ensure y[max,min] are really that
+ if (ys[0] > ys[1]) {
+ ys[0] = ys[1];
+ }
+ if (ys[3] < ys[2]) {
+ ys[3] = ys[2];
+ }
+
+ for (int i = 0; i < 5; i++) {
+ pts[i].set(0, SkIntToScalar(ys[i]) / upem);
+ }
+
+ sk_free(hhea);
+ sk_free(head);
+ return true;
+}
+
void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx,
SkPaint::FontMetrics* my) {
-#if 0
- OSStatus ATSFontGetVerticalMetrics (
- ATSFontRef iFont,
- ATSOptionFlags iOptions,
- ATSFontMetrics *oMetrics
- );
-#endif
- //SkASSERT(false);
- if (mx)
- memset(mx, 0, sizeof(SkPaint::FontMetrics));
- if (my)
- memset(my, 0, sizeof(SkPaint::FontMetrics));
- return;
+ SkPoint pts[5];
+
+ if (!init_vertical_metrics(fRec.fFontID, pts)) {
+ // these are not as accurate as init_vertical_metrics :(
+ ATSFontMetrics metrics;
+ ATSFontGetVerticalMetrics(fRec.fFontID, kATSOptionFlagsDefault,
+ &metrics);
+ pts[0].set(0, -SkFloatToScalar(metrics.ascent));
+ pts[1].set(0, -SkFloatToScalar(metrics.ascent));
+ pts[2].set(0, -SkFloatToScalar(metrics.descent));
+ pts[3].set(0, -SkFloatToScalar(metrics.descent));
+ pts[4].set(0, SkFloatToScalar(metrics.leading)); //+ or -?
+ }
+
+ SkMatrix m;
+ fRec.getSingleMatrix(&m);
+ m.mapPoints(pts, 5);
+
+ if (mx) {
+ mx->fTop = pts[0].fX;
+ mx->fAscent = pts[1].fX;
+ mx->fDescent = pts[2].fX;
+ mx->fBottom = pts[3].fX;
+ mx->fLeading = pts[4].fX;
+ }
+ if (my) {
+ my->fTop = pts[0].fY;
+ my->fAscent = pts[1].fY;
+ my->fDescent = pts[2].fY;
+ my->fBottom = pts[3].fY;
+ my->fLeading = pts[4].fY;
+ }
}
void SkScalerContext_Mac::generateImage(const SkGlyph& glyph)
@@ -226,7 +336,8 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph)
CGGlyph glyphID = glyph.getGlyphID();
CGFontRef fontRef = CGFontCreateWithPlatformFont(&fRec.fFontID);
CGContextSetFont(contextRef, fontRef);
- CGContextSetFontSize(contextRef, SkScalarToFloat(fRec.fTextSize));
+ CGContextSetFontSize(contextRef, 1); //SkScalarToFloat(fRec.fTextSize));
+ CGContextSetTextMatrix(contextRef, fTransform);
CGContextShowGlyphsAtPoint(contextRef, -glyph.fLeft,
glyph.fTop + glyph.fHeight, &glyphID, 1);
@@ -248,16 +359,6 @@ void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path)
SkASSERT(err == noErr);
}
-void SkScalerContext_Mac::generateLineHeight(SkPoint* ascent, SkPoint* descent)
-{
- ATSUTextMeasurement textAscent, textDescent;
- ByteCount actual = 0;
- OSStatus err = ::ATSUGetAttribute(fStyle,kATSULineAscentTag,sizeof(ATSUTextMeasurement),&textAscent,&actual);
- ascent->set(0,textAscent);
- err = ::ATSUGetAttribute(fStyle,kATSULineDescentTag,sizeof(ATSUTextMeasurement),&textDescent,&actual);
- descent->set(0,textDescent);
-}
-
OSStatus SkScalerContext_Mac::MoveTo(const Float32Point *pt, void *cb)
{
reinterpret_cast<SkPath*>(cb)->moveTo(F32PtToSkPoint(*pt));