Provide windows font host implementation needed to support TrueType text in pdf backend.
- Move AdvanceMetric template functions into new file SkAdvancedTypefaceMetrics.cpp Review URL: http://codereview.appspot.com/4174041 git-svn-id: http://skia.googlecode.com/svn/trunk@789 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
97b624529c
commit
6f72d1eacd
@ -107,4 +107,30 @@ public:
|
||||
SkTScopedPtr<SkAutoTArray<SkString> > fGlyphNames;
|
||||
};
|
||||
|
||||
namespace skia_advanced_typeface_metrics_utils {
|
||||
|
||||
template <typename Data>
|
||||
void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
|
||||
int startId);
|
||||
|
||||
template <typename Data>
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
|
||||
SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
|
||||
int startId);
|
||||
|
||||
template <typename Data>
|
||||
void finishRange(
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
|
||||
int endId,
|
||||
typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
|
||||
type);
|
||||
|
||||
template <typename Data, typename FontHandle>
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
|
||||
FontHandle fontHandle,
|
||||
int num_glyphs,
|
||||
bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data));
|
||||
|
||||
} // namespace skia_advanced_typeface_metrics_utils
|
||||
|
||||
#endif
|
||||
|
158
src/core/SkAdvancedTypefaceMetrics.cpp
Executable file
158
src/core/SkAdvancedTypefaceMetrics.cpp
Executable file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "SkAdvancedTypefaceMetrics.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
#ifdef SK_BUILD_FOR_UNIX
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#endif
|
||||
|
||||
namespace skia_advanced_typeface_metrics_utils {
|
||||
|
||||
template <typename Data>
|
||||
void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
|
||||
int startId) {
|
||||
range->fStartId = startId;
|
||||
range->fAdvance.setCount(0);
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
|
||||
SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
|
||||
int startId) {
|
||||
nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>);
|
||||
resetRange(nextSlot->get(), startId);
|
||||
return nextSlot->get();
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
void finishRange(
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
|
||||
int endId,
|
||||
typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
|
||||
type) {
|
||||
range->fEndId = endId;
|
||||
range->fType = type;
|
||||
int newLength;
|
||||
if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange) {
|
||||
newLength = endId - range->fStartId + 1;
|
||||
} else {
|
||||
newLength = 1;
|
||||
}
|
||||
SkASSERT(range->fAdvance.count() >= newLength);
|
||||
range->fAdvance.setCount(newLength);
|
||||
}
|
||||
|
||||
template <typename Data, typename FontHandle>
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
|
||||
FontHandle fontHandle,
|
||||
int num_glyphs,
|
||||
bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) {
|
||||
// Assuming that an ASCII representation of a width or a glyph id is,
|
||||
// on average, 3 characters long gives the following cut offs for
|
||||
// using different range types:
|
||||
// When currently in a range
|
||||
// - Removing 4 0's is a win
|
||||
// - Removing 5 repeats is a win
|
||||
// When not currently in a range
|
||||
// - Removing 1 0 is a win
|
||||
// - Removing 3 repeats is a win
|
||||
|
||||
SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result;
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange;
|
||||
curRange = appendRange(&result, 0);
|
||||
Data lastAdvance = SK_MinS16;
|
||||
int repeats = 0;
|
||||
for (int gId = 0; gId < num_glyphs; gId++) {
|
||||
Data advance;
|
||||
if (!getAdvance(fontHandle, gId, &advance)) {
|
||||
num_glyphs = (gId > 0) ? gId - 1 : 0;
|
||||
break;
|
||||
}
|
||||
if (advance == lastAdvance) {
|
||||
repeats++;
|
||||
} else if (curRange->fAdvance.count() == repeats + 1) {
|
||||
if (lastAdvance == 0 && repeats >= 0) {
|
||||
resetRange(curRange, gId);
|
||||
} else if (repeats >= 2) {
|
||||
finishRange(curRange, gId - 1,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRun);
|
||||
curRange = appendRange(&curRange->fNext, gId);
|
||||
}
|
||||
repeats = 0;
|
||||
} else {
|
||||
if (lastAdvance == 0 && repeats >= 3) {
|
||||
finishRange(curRange, gId - repeats - 2,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
curRange = appendRange(&curRange->fNext, gId);
|
||||
} else if (repeats >= 4) {
|
||||
finishRange(curRange, gId - repeats - 2,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
curRange = appendRange(&curRange->fNext, gId - repeats - 1);
|
||||
curRange->fAdvance.append(1, &lastAdvance);
|
||||
finishRange(curRange, gId - 1,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRun);
|
||||
curRange = appendRange(&curRange->fNext, gId);
|
||||
}
|
||||
repeats = 0;
|
||||
}
|
||||
curRange->fAdvance.append(1, &advance);
|
||||
lastAdvance = advance;
|
||||
}
|
||||
finishRange(curRange, num_glyphs - 1,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
return result.release();
|
||||
}
|
||||
|
||||
// Make AdvanceMetric template functions available for linking with typename
|
||||
// WidthRange and VerticalAdvanceRange.
|
||||
#ifdef SK_BUILD_FOR_WIN
|
||||
template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
|
||||
HDC hdc,
|
||||
int num_glyphs,
|
||||
bool (*getAdvance)(HDC hdc, int gId, int16_t* data));
|
||||
#elif SK_BUILD_FOR_UNIX
|
||||
template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
|
||||
FT_Face face,
|
||||
int num_glyphs,
|
||||
bool (*getAdvance)(FT_Face face, int gId, int16_t* data));
|
||||
#endif
|
||||
template void resetRange(
|
||||
SkAdvancedTypefaceMetrics::WidthRange* range,
|
||||
int startId);
|
||||
template SkAdvancedTypefaceMetrics::WidthRange* appendRange(
|
||||
SkTScopedPtr<SkAdvancedTypefaceMetrics::WidthRange >* nextSlot,
|
||||
int startId);
|
||||
template void finishRange<int16_t>(
|
||||
SkAdvancedTypefaceMetrics::WidthRange* range,
|
||||
int endId,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::MetricType type);
|
||||
|
||||
template void resetRange(
|
||||
SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range,
|
||||
int startId);
|
||||
template SkAdvancedTypefaceMetrics::VerticalAdvanceRange* appendRange(
|
||||
SkTScopedPtr<SkAdvancedTypefaceMetrics::VerticalAdvanceRange >*
|
||||
nextSlot,
|
||||
int startId);
|
||||
template void finishRange<SkAdvancedTypefaceMetrics::VerticalMetric>(
|
||||
SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range,
|
||||
int endId,
|
||||
SkAdvancedTypefaceMetrics::VerticalAdvanceRange::MetricType type);
|
||||
|
||||
} // namespace skia_advanced_typeface_metrics_utils
|
@ -1,5 +1,6 @@
|
||||
SOURCE := \
|
||||
Sk64.cpp \
|
||||
SkAdvancedTypefaceMetrics.cpp \
|
||||
SkAlphaRuns.cpp \
|
||||
SkBitmap.cpp \
|
||||
SkBitmapProcShader.cpp \
|
||||
|
@ -73,6 +73,8 @@
|
||||
#define SkASSERT_CONTINUE(pred)
|
||||
#endif
|
||||
|
||||
using namespace skia_advanced_typeface_metrics_utils;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct SkFaceRec;
|
||||
@ -331,98 +333,14 @@ static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int16_t getWidthAdvance(FT_Face face, int gId) {
|
||||
static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) {
|
||||
FT_Fixed advance = 0;
|
||||
SkAssertResult(getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance) == 0);
|
||||
return advance;
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
static void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
|
||||
int startId) {
|
||||
range->fStartId = startId;
|
||||
range->fAdvance.setCount(0);
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
static SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
|
||||
SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
|
||||
int startId) {
|
||||
nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>);
|
||||
resetRange(nextSlot->get(), startId);
|
||||
return nextSlot->get();
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
static void finishRange(
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
|
||||
int endId,
|
||||
typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
|
||||
type) {
|
||||
range->fEndId = endId;
|
||||
range->fType = type;
|
||||
int newLength;
|
||||
if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange)
|
||||
newLength = endId - range->fStartId + 1;
|
||||
else
|
||||
newLength = 1;
|
||||
SkASSERT(range->fAdvance.count() >= newLength);
|
||||
range->fAdvance.setCount(newLength);
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
static SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
|
||||
FT_Face face, Data (*getAdvance)(FT_Face face, int gId)) {
|
||||
// Assuming that an ASCII representation of a width or a glyph id is,
|
||||
// on average, 3 characters long gives the following cut offs for
|
||||
// using different range types:
|
||||
// When currently in a range
|
||||
// - Removing 4 0's is a win
|
||||
// - Removing 5 repeats is a win
|
||||
// When not currently in a range
|
||||
// - Removing 1 0 is a win
|
||||
// - Removing 3 repeats is a win
|
||||
|
||||
SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result;
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange;
|
||||
curRange = appendRange(&result, 0);
|
||||
Data lastAdvance = SHRT_MIN;
|
||||
int repeats = 0;
|
||||
for (int gId = 0; gId < face->num_glyphs; gId++) {
|
||||
Data advance = getAdvance(face, gId);
|
||||
if (advance == lastAdvance) {
|
||||
repeats++;
|
||||
} else if (curRange->fAdvance.count() == repeats + 1) {
|
||||
if (lastAdvance == 0 && repeats >= 0) {
|
||||
resetRange(curRange, gId);
|
||||
} else if (repeats >= 2) {
|
||||
finishRange(curRange, gId - 1,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRun);
|
||||
curRange = appendRange(&curRange->fNext, gId);
|
||||
}
|
||||
repeats = 0;
|
||||
} else {
|
||||
if (lastAdvance == 0 && repeats >= 3) {
|
||||
finishRange(curRange, gId - repeats - 2,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
curRange = appendRange(&curRange->fNext, gId);
|
||||
} else if (repeats >= 4) {
|
||||
finishRange(curRange, gId - repeats - 2,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
curRange = appendRange(&curRange->fNext, gId - repeats - 1);
|
||||
curRange->fAdvance.append(1, &lastAdvance);
|
||||
finishRange(curRange, gId - 1,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRun);
|
||||
curRange = appendRange(&curRange->fNext, gId);
|
||||
}
|
||||
repeats = 0;
|
||||
}
|
||||
curRange->fAdvance.append(1, &advance);
|
||||
lastAdvance = advance;
|
||||
if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
|
||||
return false;
|
||||
}
|
||||
finishRange(curRange, face->num_glyphs - 1,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
return result.release();
|
||||
SkASSERT(data);
|
||||
*data = advance;
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
@ -499,6 +417,7 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
// Figure out a good guess for StemV - Min width of i, I, !, 1.
|
||||
// This probably isn't very good with an italic font.
|
||||
int16_t min_width = SHRT_MAX;
|
||||
info->fStemV = 0;
|
||||
char stem_chars[] = {'i', 'I', '!', '1'};
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
|
||||
FT_BBox bbox;
|
||||
@ -550,7 +469,7 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
info->fGlyphWidths->fAdvance.append(1, &advance);
|
||||
finishRange(info->fGlyphWidths.get(), 0,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kDefault);
|
||||
} else if(!cid) {
|
||||
} else if (!cid) {
|
||||
appendRange(&info->fGlyphWidths, 0);
|
||||
// So as to not blow out the stack, get advances in batches.
|
||||
for (int gID = 0; gID < face->num_glyphs; gID += 128) {
|
||||
@ -568,7 +487,8 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
} else {
|
||||
info->fGlyphWidths.reset(getAdvanceData(face, &getWidthAdvance));
|
||||
info->fGlyphWidths.reset(
|
||||
getAdvanceData(face, face->num_glyphs, &getWidthAdvance));
|
||||
}
|
||||
|
||||
if (info->fType == SkAdvancedTypefaceMetrics::kType1_Font) {
|
||||
|
151
src/ports/SkFontHost_win.cpp
Normal file → Executable file
151
src/ports/SkFontHost_win.cpp
Normal file → Executable file
@ -19,6 +19,8 @@
|
||||
|
||||
#include "SkFontHost.h"
|
||||
#include "SkDescriptor.h"
|
||||
#include "SkAdvancedTypefaceMetrics.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkThread.h"
|
||||
|
||||
#ifdef WIN32
|
||||
@ -28,6 +30,8 @@
|
||||
// client3d has to undefine this for now
|
||||
#define CAN_USE_LOGFONT_NAME
|
||||
|
||||
using namespace skia_advanced_typeface_metrics_utils;
|
||||
|
||||
static SkMutex gFTMutex;
|
||||
|
||||
static const uint16_t BUFFERSIZE = (16384 - 32);
|
||||
@ -456,11 +460,133 @@ SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
|
||||
// Initialize the MAT2 structure to the identify transformation matrix.
|
||||
static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
|
||||
SkScalarToFIXED(0), SkScalarToFIXED(1)};
|
||||
int flags = GGO_METRICS | GGO_GLYPH_INDEX;
|
||||
GLYPHMETRICS gm;
|
||||
if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {
|
||||
return false;
|
||||
}
|
||||
SkASSERT(advance);
|
||||
*advance = gm.gmCellIncX;
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
LogFontTypeface* rec = LogFontTypeface::FindById(fontID);
|
||||
LOGFONT lf = rec->logFont();
|
||||
SkAdvancedTypefaceMetrics* info = NULL;
|
||||
|
||||
HDC hdc = CreateCompatibleDC(NULL);
|
||||
HFONT font = CreateFontIndirect(&lf);
|
||||
HFONT savefont = (HFONT)SelectObject(hdc, font);
|
||||
HFONT designFont = NULL;
|
||||
|
||||
// To request design units, create a logical font whose height is specified
|
||||
// as unitsPerEm.
|
||||
OUTLINETEXTMETRIC otm;
|
||||
if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm) ||
|
||||
!GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
|
||||
goto Error;
|
||||
}
|
||||
lf.lfHeight = -SkToS32(otm.otmEMSquare);
|
||||
designFont = CreateFontIndirect(&lf);
|
||||
SelectObject(hdc, designFont);
|
||||
if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
info = new SkAdvancedTypefaceMetrics;
|
||||
#ifdef UNICODE
|
||||
// Get the buffer size needed first.
|
||||
size_t str_len = WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, NULL,
|
||||
0, NULL, NULL);
|
||||
// Allocate a buffer (str_len already has terminating null accounted for).
|
||||
char *familyName = new char[str_len];
|
||||
// Now actually convert the string.
|
||||
WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, familyName, str_len,
|
||||
NULL, NULL);
|
||||
info->fFontName.set(familyName);
|
||||
delete [] familyName;
|
||||
#else
|
||||
info->fFontName.set(lf.lfFaceName);
|
||||
#endif
|
||||
|
||||
if (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE) {
|
||||
info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
|
||||
} else {
|
||||
info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
|
||||
}
|
||||
info->fEmSize = otm.otmEMSquare;
|
||||
info->fMultiMaster = false;
|
||||
|
||||
info->fStyle = 0;
|
||||
// If this bit is clear the font is a fixed pitch font.
|
||||
if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
|
||||
}
|
||||
if (otm.otmTextMetrics.tmItalic) {
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
|
||||
}
|
||||
// Setting symbolic style by default for now.
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;
|
||||
if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
|
||||
} else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
|
||||
}
|
||||
|
||||
// The main italic angle of the font, in tenths of a degree counterclockwise
|
||||
// from vertical.
|
||||
info->fItalicAngle = otm.otmItalicAngle / 10;
|
||||
info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
|
||||
info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
|
||||
// TODO(ctguil): Use alternate cap height calculation.
|
||||
// MSDN says otmsCapEmHeight is not support but it is returning a value on
|
||||
// my Win7 box.
|
||||
info->fCapHeight = otm.otmsCapEmHeight;
|
||||
info->fBBox =
|
||||
SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
|
||||
otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
|
||||
|
||||
// Figure out a good guess for StemV - Min width of i, I, !, 1.
|
||||
// This probably isn't very good with an italic font.
|
||||
int16_t min_width = SHRT_MAX;
|
||||
info->fStemV = 0;
|
||||
char stem_chars[] = {'i', 'I', '!', '1'};
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
|
||||
ABC abcWidths;
|
||||
if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
|
||||
int16_t width = abcWidths.abcB;
|
||||
if (width > 0 && width < min_width) {
|
||||
min_width = width;
|
||||
info->fStemV = min_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If bit 1 is set, the font may not be embedded in a document.
|
||||
// If bit 1 is clear, the font can be embedded.
|
||||
// If bit 2 is set, the embedding is read-only.
|
||||
if (otm.otmfsType & 0x1) {
|
||||
info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
|
||||
} else if (perGlyphInfo) {
|
||||
info->fGlyphWidths.reset(
|
||||
getAdvanceData(hdc, SHRT_MAX, &getWidthAdvance));
|
||||
}
|
||||
|
||||
Error:
|
||||
SelectObject(hdc, savefont);
|
||||
DeleteObject(designFont);
|
||||
DeleteObject(font);
|
||||
DeleteDC(hdc);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
|
||||
@ -471,8 +597,25 @@ SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
|
||||
}
|
||||
|
||||
SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
|
||||
SkASSERT(!"SkFontHost::OpenStream unimplemented");
|
||||
return NULL;
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
LogFontTypeface* rec = LogFontTypeface::FindById(uniqueID);
|
||||
|
||||
HDC hdc = ::CreateCompatibleDC(NULL);
|
||||
HFONT font = CreateFontIndirect(&rec->logFont());
|
||||
HFONT savefont = (HFONT)SelectObject(hdc, font);
|
||||
|
||||
size_t bufferSize = GetFontData(hdc, 0, 0, NULL, 0);
|
||||
SkMemoryStream* stream = new SkMemoryStream(bufferSize);
|
||||
if (!GetFontData(hdc, 0, 0, (void*)stream->getMemoryBase(), bufferSize)) {
|
||||
delete stream;
|
||||
stream = NULL;
|
||||
}
|
||||
|
||||
SelectObject(hdc, savefont);
|
||||
DeleteObject(font);
|
||||
DeleteDC(hdc);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
|
||||
|
@ -293,6 +293,7 @@
|
||||
<ClCompile Include="..\..\samplecode\SampleVertices.cpp" />
|
||||
<ClCompile Include="..\..\samplecode\SampleXfermodes.cpp" />
|
||||
<ClCompile Include="..\..\src\core\Sk64.cpp" />
|
||||
<ClCompile Include="..\..\src\core\SkAdvancedTypefaceMetrics.cpp" />
|
||||
<ClCompile Include="..\..\src\core\SkAlphaRuns.cpp" />
|
||||
<ClCompile Include="..\..\src\core\SkBitmap.cpp" />
|
||||
<ClCompile Include="..\..\src\core\SkBitmapProcShader.cpp" />
|
||||
@ -476,4 +477,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
Loading…
Reference in New Issue
Block a user