#include "SkGlyph.h"
#include "SkHRESULT.h"
#include "SkMaskGamma.h"
+#include "SkMatrix22.h"
#include "SkOTTable_maxp.h"
#include "SkOTTable_name.h"
#include "SkOTUtils.h"
return SkFixedToFIXED(SkScalarToFixed(x));
}
+static inline SkScalar SkFIXEDToScalar(FIXED x) {
+ return SkFixedToScalar(SkFIXEDToFixed(x));
+}
+
static unsigned calculateGlyphCount(HDC hdc, const LOGFONT& lf) {
TEXTMETRIC textMetric;
if (0 == GetTextMetrics(hdc, &textMetric)) {
virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
virtual size_t onGetTableData(SkFontTableTag, size_t offset,
size_t length, void* data) const SK_OVERRIDE;
- virtual SkTypeface* onRefMatchingStyle(Style) const SK_OVERRIDE;
};
class FontMemResourceTypeface : public LogFontTypeface {
public:
/**
- * Takes ownership of fontMemResource.
- */
- FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) :
- LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) {
- }
-
- HANDLE fFontMemResource;
-
- /**
* The created FontMemResourceTypeface takes ownership of fontMemResource.
*/
static FontMemResourceTypeface* Create(const LOGFONT& lf, HANDLE fontMemResource) {
}
private:
+ /**
+ * Takes ownership of fontMemResource.
+ */
+ FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) :
+ LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) {
+ }
+
+ HANDLE fFontMemResource;
+
typedef LogFontTypeface INHERITED;
};
*/
SkMatrix fG_inv;
enum Type {
- kTrueType_Type, kBitmap_Type,
+ kTrueType_Type, kBitmap_Type, kLine_Type
} fType;
TEXTMETRIC fTM;
};
fRec.getSingleMatrix(&A);
A.mapPoints(&h, 1);
- // Find the Given's matrix [[c, -s],[s, c]] which rotates the baseline vector h
- // (where the baseline is mapped to) to the positive horizontal axis.
- const SkScalar& a = h.fX;
- const SkScalar& b = h.fY;
- SkScalar c, s;
- if (0 == b) {
- c = SkDoubleToScalar(_copysign(SK_Scalar1, a));
- s = 0;
- } else if (0 == a) {
- c = 0;
- s = SkDoubleToScalar(-_copysign(SK_Scalar1, b));
- } else if (SkScalarAbs(b) > SkScalarAbs(a)) {
- SkScalar t = a / b;
- SkScalar u = SkDoubleToScalar(_copysign(SkScalarSqrt(SK_Scalar1 + t*t), b));
- s = -1 / u;
- c = -s * t;
- } else {
- SkScalar t = b / a;
- SkScalar u = SkDoubleToScalar(_copysign(SkScalarSqrt(SK_Scalar1 + t*t), a));
- c = 1 / u;
- s = -c * t;
- }
-
- // G is the Given's Matrix for A (rotational matrix such that GA[0][1] == 0).
+ // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
SkMatrix G;
- G.setAll(c, -s, 0,
- s, c, 0,
- 0, 0, SkScalarToPersp(SK_Scalar1));
+ SkComputeGivensRotation(h, &G);
// GA is the matrix A with rotation removed.
SkMatrix GA(G);
fTM.tmPitchAndFamily = TMPF_TRUETYPE;
}
}
- // Used a logfont on a memory context, should never get a device font.
- // Therefore all TMPF_DEVICE will be PostScript fonts.
-
- // If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE must be set,
- // otherwise we have a vector FON, which we don't support.
- // This was determined by testing with Type1 PFM/PFB and OpenTypeCFF OTF,
- // as well as looking at Wine bugs and sources.
- SkASSERT(!(fTM.tmPitchAndFamily & TMPF_VECTOR) ||
- (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)));
XFORM xform;
if (fTM.tmPitchAndFamily & TMPF_VECTOR) {
- // Truetype or PostScript.
- // Stroked FON also gets here (TMPF_VECTOR), but we don't handle it.
- fType = SkScalerContext_GDI::kTrueType_Type;
+ // Used a logfont on a memory context, should never get a device font.
+ // Therefore all TMPF_DEVICE will be PostScript fonts.
+
+ // If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE means that
+ // we have an outline font. Otherwise we have a vector FON, which is
+ // scalable, but not an outline font.
+ // This was determined by testing with Type1 PFM/PFB and
+ // OpenTypeCFF OTF, as well as looking at Wine bugs and sources.
+ if (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)) {
+ // Truetype or PostScript.
+ fType = SkScalerContext_GDI::kTrueType_Type;
+ } else {
+ // Stroked FON.
+ fType = SkScalerContext_GDI::kLine_Type;
+ }
// fPost2x2 is column-major, left handed (y down).
// XFORM 2x2 is row-major, left handed (y down).
*
* When GGI_MARK_NONEXISTING_GLYPHS is not specified and a character does not map to a
* glyph, then the 'default character's glyph is returned instead. The 'default character'
- * is available in fTM.tmDefaultChar. FON fonts have adefault character, and there exists a
- * usDefaultChar in the 'OS/2' table, version 2 and later. If there is no
+ * is available in fTM.tmDefaultChar. FON fonts have a default character, and there exists
+ * a usDefaultChar in the 'OS/2' table, version 2 and later. If there is no
* 'default character' specified by the font, then often the first character found is used.
*
* When GGI_MARK_NONEXISTING_GLYPHS is specified and a character does not map to a glyph,
DWORD result = GetGlyphIndicesW(fDDC, utf16, 1, &index, GGI_MARK_NONEXISTING_GLYPHS);
if (result == GDI_ERROR
|| 0xFFFF == index
- || (0x1F == index && fType == SkScalerContext_GDI::kBitmap_Type /*&& winVer < Vista */))
+ || (0x1F == index &&
+ (fType == SkScalerContext_GDI::kBitmap_Type ||
+ fType == SkScalerContext_GDI::kLine_Type)
+ /*&& winVer < Vista */)
+ )
{
index = 0;
}
void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
SkASSERT(fDDC);
- if (fType == SkScalerContext_GDI::kBitmap_Type) {
+ if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
SIZE size;
WORD glyphs = glyph->getGlyphID(0);
if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) {
glyph->fHeight = SkToS16(size.cy);
glyph->fTop = SkToS16(-fTM.tmAscent);
+ // Bitmap FON cannot underhang, but vector FON may.
+ // There appears no means of determining underhang of vector FON.
glyph->fLeft = SkToS16(0);
glyph->fAdvanceX = SkIntToFixed(glyph->fWidth);
glyph->fAdvanceY = 0;
+ // Vector FON will transform nicely, but bitmap FON do not.
+ if (fType == SkScalerContext_GDI::kLine_Type) {
+ SkRect bounds = SkRect::MakeXYWH(glyph->fLeft, glyph->fTop,
+ glyph->fWidth, glyph->fHeight);
+ SkMatrix m;
+ m.setAll(SkFIXEDToScalar(fMat22.eM11), -SkFIXEDToScalar(fMat22.eM21), 0,
+ -SkFIXEDToScalar(fMat22.eM12), SkFIXEDToScalar(fMat22.eM22), 0,
+ 0, 0, SkScalarToPersp(SK_Scalar1));
+ m.mapRect(&bounds);
+ bounds.roundOut();
+ glyph->fLeft = SkScalarTruncToInt(bounds.fLeft);
+ glyph->fTop = SkScalarTruncToInt(bounds.fTop);
+ glyph->fWidth = SkScalarTruncToInt(bounds.width());
+ glyph->fHeight = SkScalarTruncToInt(bounds.height());
+ }
+
// Apply matrix to advance.
- glyph->fAdvanceY = SkFixedMul(SkFIXEDToFixed(fMat22.eM21), glyph->fAdvanceX);
+ glyph->fAdvanceY = SkFixedMul(-SkFIXEDToFixed(fMat22.eM12), glyph->fAdvanceX);
glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvanceX);
return;
SkASSERT(fDDC);
#ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
- if (fType == SkScalerContext_GDI::kBitmap_Type) {
+ if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
#endif
if (mx) {
mx->fTop = SkIntToScalar(-fTM.tmAscent);
mx->fDescent = SkIntToScalar(-otm.otmDescent);
mx->fBottom = SkIntToScalar(otm.otmrcFontBox.right);
mx->fLeading = SkIntToScalar(otm.otmLineGap);
+ mx->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize);
+ mx->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition);
+
+ mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
}
if (my) {
my->fMaxCharWidth = SkIntToScalar(otm.otmTextMetrics.tmMaxCharWidth);
my->fXMin = SkIntToScalar(otm.otmrcFontBox.left);
my->fXMax = SkIntToScalar(otm.otmrcFontBox.right);
+ my->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize);
+ my->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition);
+
+ my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
#endif
my->fXHeight = SkIntToScalar(otm.otmsXHeight);
for (int i = 0; i < 256; i++) {
float x = i / 255.f;
x = sk_float_pow(x, ee);
- int xx = SkScalarRound(SkFloatToScalar(x * 255));
+ int xx = SkScalarRoundToInt(x * 255);
table[i] = SkToU8(xx);
}
}
HFONT fFont;
HFONT fSavefont;
};
+#define SkAutoHDC(...) SK_REQUIRE_LOCAL_VAR(SkAutoHDC)
int LogFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
uint16_t userGlyphs[], int glyphCount) const
}
unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
- SkScalerContext::kAutohinting_Flag |
+ SkScalerContext::kForceAutohinting_Flag |
SkScalerContext::kEmbeddedBitmapText_Flag |
SkScalerContext::kEmbolden_Flag |
SkScalerContext::kLCD_BGROrder_Flag |
}
}
-static SkTypeface* create_typeface(const SkTypeface* familyFace,
- const char familyName[],
- unsigned styleBits) {
- LOGFONT lf;
- if (NULL == familyFace && NULL == familyName) {
- lf = get_default_font();
- } else if (familyFace) {
- LogFontTypeface* face = (LogFontTypeface*)familyFace;
- lf = face->fLogFont;
- } else {
- logfont_for_name(familyName, &lf);
- }
- setStyle(&lf, (SkTypeface::Style)styleBits);
- return SkCreateTypefaceFromLOGFONT(lf);
-}
-
-SkTypeface* LogFontTypeface::onRefMatchingStyle(Style style) const {
- return create_typeface(this, NULL, style);
-}
-
///////////////////////////////////////////////////////////////////////////////
#include "SkFontMgr.h"
}
protected:
- virtual int onCountFamilies() SK_OVERRIDE {
+ virtual int onCountFamilies() const SK_OVERRIDE {
return fLogFontArray.count();
}
- virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
+ virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
tchar_to_skstring(fLogFontArray[index].elfLogFont.lfFaceName, familyName);
}
- virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE {
+ virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
return SkNEW_ARGS(SkFontStyleSetGDI, (fLogFontArray[index].elfLogFont.lfFaceName));
}
- virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE {
+ virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
if (NULL == familyName) {
familyName = ""; // do we need this check???
}
}
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
- const SkFontStyle& fontstyle) SK_OVERRIDE {
+ const SkFontStyle& fontstyle) const SK_OVERRIDE {
// could be in base impl
SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
return sset->matchStyle(fontstyle);
}
virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
- const SkFontStyle& fontstyle) SK_OVERRIDE {
+ const SkFontStyle& fontstyle) const SK_OVERRIDE {
// could be in base impl
SkString familyName;
((LogFontTypeface*)familyMember)->getFamilyName(&familyName);
return this->matchFamilyStyle(familyName.c_str(), fontstyle);
}
- virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
return create_from_stream(stream);
}
- virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
// could be in base impl
SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
return this->createFromStream(stream);
}
- virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
// could be in base impl
SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
return this->createFromStream(stream);
}
virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
- unsigned styleBits) SK_OVERRIDE {
- return create_typeface(NULL, familyName, styleBits);
+ unsigned styleBits) const SK_OVERRIDE {
+ LOGFONT lf;
+ if (NULL == familyName) {
+ lf = get_default_font();
+ } else {
+ logfont_for_name(familyName, &lf);
+ }
+ setStyle(&lf, (SkTypeface::Style)styleBits);
+ return SkCreateTypefaceFromLOGFONT(lf);
}
private:
///////////////////////////////////////////////////////////////////////////////
-#ifndef SK_FONTHOST_USES_FONTMGR
-
-SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
- const char familyName[],
- SkTypeface::Style styleBits) {
- return create_typeface(familyFace, familyName, styleBits);
-}
-
-SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
- SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
- return stream.get() ? CreateTypefaceFromStream(stream) : NULL;
-}
-
-SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
- return create_from_stream(stream);
-}
-
-#endif
-
SkFontMgr* SkFontMgr_New_GDI() {
return SkNEW(SkFontMgrGDI);
}