本文整理汇总了C++中TextRun::length方法的典型用法代码示例。如果您正苦于以下问题:C++ TextRun::length方法的具体用法?C++ TextRun::length怎么用?C++ TextRun::length使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TextRun
的用法示例。
在下文中一共展示了TextRun::length方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: offsetForPositionForComplexText
int Font::offsetForPositionForComplexText(const TextRun& run, float x,
bool includePartialGlyphs) const
{
// (Mac code ignores includePartialGlyphs, and they don't know what it's
// supposed to do, so we just ignore it as well.)
TextRunWalker walker(run, 0, 0, this);
walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing());
// If this is RTL text, the first glyph from the left is actually the last
// code point. So we need to know how many code points there are total in
// order to subtract. This is different from the length of the TextRun
// because UTF-16 surrogate pairs are a single code point, but 32-bits long.
// In LTR we leave this as 0 so that we get the correct value for
// |basePosition|, below.
unsigned totalCodePoints = 0;
if (walker.rtl()) {
ssize_t offset = 0;
while (offset < run.length()) {
utf16_to_code_point(run.characters(), run.length(), &offset);
totalCodePoints++;
}
}
unsigned basePosition = totalCodePoints;
// For RTL:
// code-point order: abcd efg hijkl
// on screen: lkjih gfe dcba
// ^ ^
// | |
// basePosition--| |
// totalCodePoints----|
// Since basePosition is currently the total number of code-points, the
// first thing we do is decrement it so that it's pointing to the start of
// the current script-run.
//
// For LTR, basePosition is zero so it already points to the start of the
// first script run.
while (walker.nextScriptRun()) {
if (walker.rtl())
basePosition -= walker.numCodePoints();
if (x >= 0 && x < static_cast<int>(walker.width())) {
// The x value in question is within this script run. We consider
// each glyph in presentation order and stop when we find the one
// covering this position.
const int glyphIndex = glyphIndexForXPositionInScriptRun(walker, x);
// Now that we have a glyph index, we have to turn that into a
// code-point index. Because of ligatures, several code-points may
// have gone into a single glyph. We iterate over the clusters log
// and find the first code-point which contributed to the glyph.
// Some shapers (i.e. Khmer) will produce cluster logs which report
// that /no/ code points contributed to certain glyphs. Because of
// this, we take any code point which contributed to the glyph in
// question, or any subsequent glyph. If we run off the end, then
// we take the last code point.
const unsigned short* log = walker.logClusters();
for (unsigned j = 0; j < walker.numCodePoints(); ++j) {
if (log[j] >= glyphIndex)
return basePosition + j;
}
return basePosition + walker.numCodePoints() - 1;
}
x -= walker.width();
if (!walker.rtl())
basePosition += walker.numCodePoints();
}
return basePosition;
}
示例2: walk
void walk(const TextRun& run, bool isVerticalText, const String& language, int from, int to)
{
// Should hold true for SVG text, otherwhise sth. is wrong
ASSERT(to - from == run.length());
Vector<SVGGlyphIdentifier::ArabicForm> chars(charactersWithArabicForm(String(run.data(from), run.length()), run.rtl()));
SVGGlyphIdentifier identifier;
bool foundGlyph = false;
int characterLookupRange;
int endOfScanRange = to + m_walkerData.extraCharsAvailable;
bool haveAltGlyph = false;
SVGGlyphIdentifier altGlyphIdentifier;
if (RenderObject* renderObject = run.referencingRenderObject()) {
if (renderObject->element() && renderObject->element()->hasTagName(SVGNames::altGlyphTag)) {
SVGGlyphElement* glyphElement = static_cast<SVGAltGlyphElement*>(renderObject->element())->glyphElement();
if (glyphElement) {
haveAltGlyph = true;
altGlyphIdentifier = glyphElement->buildGlyphIdentifier();
altGlyphIdentifier.isValid = true;
altGlyphIdentifier.nameLength = to - from;
}
}
}
for (int i = from; i < to; ++i) {
// If characterLookupRange is > 0, then the font defined ligatures (length of unicode property value > 1).
// We have to check wheter the current character & the next character define a ligature. This needs to be
// extended to the n-th next character (where n is 'characterLookupRange'), to check for any possible ligature.
characterLookupRange = endOfScanRange - i;
String lookupString(run.data(i), characterLookupRange);
Vector<SVGGlyphIdentifier> glyphs;
if (haveAltGlyph)
glyphs.append(altGlyphIdentifier);
else
m_fontElement->getGlyphIdentifiersForString(lookupString, glyphs);
Vector<SVGGlyphIdentifier>::iterator it = glyphs.begin();
Vector<SVGGlyphIdentifier>::iterator end = glyphs.end();
for (; it != end; ++it) {
identifier = *it;
if (identifier.isValid && isCompatibleGlyph(identifier, isVerticalText, language, chars, i, i + identifier.nameLength)) {
ASSERT(characterLookupRange > 0);
i += identifier.nameLength - 1;
m_walkerData.charsConsumed += identifier.nameLength;
m_walkerData.glyphName = identifier.glyphName;
foundGlyph = true;
SVGGlyphElement::inheritUnspecifiedAttributes(identifier, m_fontData);
break;
}
}
if (!foundGlyph) {
++m_walkerData.charsConsumed;
if (SVGMissingGlyphElement* element = m_fontElement->firstMissingGlyphElement()) {
// <missing-glyph> element support
identifier = SVGGlyphElement::buildGenericGlyphIdentifier(element);
SVGGlyphElement::inheritUnspecifiedAttributes(identifier, m_fontData);
identifier.isValid = true;
} else {
// Fallback to system font fallback
TextRun subRun(run);
subRun.setText(subRun.data(i), 1);
(*m_walkerMissingGlyphCallback)(subRun, m_walkerData);
continue;
}
}
if (!(*m_walkerCallback)(identifier, m_walkerData))
break;
foundGlyph = false;
}
}
示例3: fromRawData
static const QString qstring(const TextRun& run)
{
// We don't detach
return QString::fromRawData(reinterpret_cast<const QChar*>(run.characters()), run.length());
}
示例4: drawComplexText
void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
{
if (to < 0)
to = run.length();
QPainter *p = ctx->platformContext();
if (ctx->textDrawingMode() & cTextFill) {
if (ctx->fillGradient()) {
QBrush brush(*ctx->fillGradient()->platformGradient());
brush.setTransform(ctx->fillGradient()->gradientSpaceTransform());
p->setPen(QPen(brush, 0));
} else if (ctx->fillPattern()) {
TransformationMatrix affine;
p->setPen(QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0));
} else
p->setPen(QColor(ctx->fillColor()));
}
if (ctx->textDrawingMode() & cTextStroke) {
if (ctx->strokeGradient()) {
QBrush brush(*ctx->strokeGradient()->platformGradient());
brush.setTransform(ctx->strokeGradient()->gradientSpaceTransform());
p->setPen(QPen(brush, ctx->strokeThickness()));
} else if (ctx->strokePattern()) {
TransformationMatrix affine;
p->setPen(QPen(QBrush(ctx->strokePattern()->createPlatformPattern(affine)), ctx->strokeThickness()));
} else
p->setPen(QPen(QColor(ctx->strokeColor()), ctx->strokeThickness()));
}
const QString string = fixSpacing(qstring(run));
// text shadow
IntSize shadowSize;
int shadowBlur;
Color shadowColor;
bool hasShadow = ctx->textDrawingMode() == cTextFill && ctx->getShadow(shadowSize, shadowBlur, shadowColor);
if (from > 0 || to < run.length()) {
QTextLayout layout(string, font());
QTextLine line = setupLayout(&layout, run);
float x1 = line.cursorToX(from);
float x2 = line.cursorToX(to);
if (x2 < x1)
qSwap(x1, x2);
QFontMetrics fm(font());
int ascent = fm.ascent();
QRectF clip(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
if (hasShadow) {
// TODO: when blur support is added, the clip will need to account
// for the blur radius
qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
if (shadowSize.width() > 0)
dx2 = shadowSize.width();
else
dx1 = -shadowSize.width();
if (shadowSize.height() > 0)
dy2 = shadowSize.height();
else
dy1 = -shadowSize.height();
// expand the clip rect to include the text shadow as well
clip.adjust(dx1, dx2, dy1, dy2);
}
p->save();
p->setClipRect(clip.toRect());
QPointF pt(point.x(), point.y() - ascent);
if (hasShadow) {
p->save();
p->setPen(QColor(shadowColor));
p->translate(shadowSize.width(), shadowSize.height());
line.draw(p, pt);
p->restore();
}
line.draw(p, pt);
p->restore();
return;
}
p->setFont(font());
QPointF pt(point.x(), point.y());
int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
if (hasShadow) {
// TODO: text shadow blur support
p->save();
p->setPen(QColor(shadowColor));
p->translate(shadowSize.width(), shadowSize.height());
p->drawText(pt, string, flags, run.padding());
p->restore();
}
if (ctx->textDrawingMode() & cTextStroke) {
QPainterPath path;
path.addText(pt, font(), string);
p->strokePath(path, p->pen());
}
if (ctx->textDrawingMode() & cTextFill)
p->drawText(pt, string, flags, run.padding());
//.........这里部分代码省略.........
示例5: drawBidiText
float GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const FloatPoint& point, Font::CustomFontNotReadyAction customFontNotReadyAction, BidiStatus* status, int length)
#endif
{
if (paintingDisabled())
#if !PLATFORM(IOS)
return;
#else
return 0;
#endif
BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
#if !PLATFORM(IOS)
bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride()));
#else
bidiResolver.setStatus(status ? *status : BidiStatus(run.direction(), run.directionalOverride()));
#endif
bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));
// FIXME: This ownership should be reversed. We should pass BidiRunList
// to BidiResolver in createBidiRunsForLine.
BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
#if !PLATFORM(IOS)
bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()));
#else
bidiResolver.createBidiRunsForLine(TextRunIterator(&run, length < 0 ? run.length() : length));
#endif
if (!bidiRuns.runCount())
#if !PLATFORM(IOS)
return;
#else
return 0;
#endif
FloatPoint currPoint = point;
BidiCharacterRun* bidiRun = bidiRuns.firstRun();
while (bidiRun) {
TextRun subrun = run.subRun(bidiRun->start(), bidiRun->stop() - bidiRun->start());
bool isRTL = bidiRun->level() % 2;
subrun.setDirection(isRTL ? RTL : LTR);
subrun.setDirectionalOverride(bidiRun->dirOverride(false));
#if !PLATFORM(IOS)
font.drawText(this, subrun, currPoint, 0, -1, customFontNotReadyAction);
bidiRun = bidiRun->next();
// FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here.
if (bidiRun)
currPoint.move(font.width(subrun), 0);
#else
float width = font.drawText(this, subrun, currPoint, 0, -1, customFontNotReadyAction);
currPoint.move(width, 0);
bidiRun = bidiRun->next();
#endif
}
#if PLATFORM(IOS)
if (status)
*status = bidiResolver.status();
#endif
bidiRuns.deleteRuns();
#if PLATFORM(IOS)
return currPoint.x() - static_cast<float>(point.x());
#endif
}
示例6: codePath
Font::CodePath Font::codePath(const TextRun& run) const
{
if (s_codePath != Auto)
return s_codePath;
#if PLATFORM(QT)
if (run.padding() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing())
return Complex;
#endif
CodePath result = Simple;
// Start from 0 since drawing and highlighting also measure the characters before run->from
for (int i = 0; i < run.length(); i++) {
const UChar c = run[i];
if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
continue;
if (c <= 0x36F)
return Complex;
if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
continue;
if (c <= 0x05CF)
return Complex;
if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
continue;
if (c <= 0x1059)
return Complex;
if (c < 0x1100) // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A)
continue;
if (c <= 0x11FF)
return Complex;
if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian
continue;
if (c <= 0x18AF)
return Complex;
if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
continue;
if (c <= 0x194F)
return Complex;
if (c < 0x1E00) // U+1E00 through U+2000 characters with diacritics and stacked diacritics
continue;
if (c <= 0x2000) {
result = SimpleWithGlyphOverflow;
continue;
}
if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
continue;
if (c <= 0x20FF)
return Complex;
if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks
continue;
if (c <= 0xFE2F)
return Complex;
}
if (typesettingFeatures())
return Complex;
return result;
}
示例7: drawTextCommon
static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to, const QFont& font, bool isComplexText)
{
if (to < 0)
to = run.length();
QPainter *p = ctx->platformContext();
QPen textFillPen;
if (ctx->textDrawingMode() & cTextFill) {
if (ctx->fillGradient()) {
QBrush brush(*ctx->fillGradient()->platformGradient());
brush.setTransform(ctx->fillGradient()->gradientSpaceTransform());
textFillPen = QPen(brush, 0);
} else if (ctx->fillPattern()) {
AffineTransform affine;
textFillPen = QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0);
} else
textFillPen = QPen(QColor(ctx->fillColor()));
}
QPen textStrokePen;
if (ctx->textDrawingMode() & cTextStroke) {
if (ctx->strokeGradient()) {
QBrush brush(*ctx->strokeGradient()->platformGradient());
brush.setTransform(ctx->strokeGradient()->gradientSpaceTransform());
textStrokePen = QPen(brush, ctx->strokeThickness());
} else if (ctx->strokePattern()) {
AffineTransform affine;
QBrush brush(ctx->strokePattern()->createPlatformPattern(affine));
textStrokePen = QPen(brush, ctx->strokeThickness());
} else
textStrokePen = QPen(QColor(ctx->strokeColor()), ctx->strokeThickness());
}
String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
QString string = fromRawDataWithoutRef(sanitized);
QPointF pt(point.x(), point.y());
// text shadow
IntSize shadowSize;
int shadowBlur;
Color shadowColor;
bool hasShadow = ctx->textDrawingMode() == cTextFill && ctx->getShadow(shadowSize, shadowBlur, shadowColor);
if (from > 0 || to < run.length()) {
if (isComplexText) {
QTextLayout layout(string, font);
QTextLine line = setupLayout(&layout, run);
float x1 = line.cursorToX(from);
float x2 = line.cursorToX(to);
if (x2 < x1)
qSwap(x1, x2);
QFontMetrics fm(font);
int ascent = fm.ascent();
QRectF clip(fm.boundingRect(string));
if (hasShadow) {
// TODO: when blur support is added, the clip will need to account
// for the blur radius
qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
if (shadowSize.width() > 0)
dx2 = shadowSize.width();
else
dx1 = -shadowSize.width();
if (shadowSize.height() > 0)
dy2 = shadowSize.height();
else
dy1 = -shadowSize.height();
// expand the clip rect to include the text shadow as well
clip.adjust(dx1, dx2, dy1, dy2);
}
p->save();
//p->setClipRect(clip.toRect(), Qt::IntersectClip);
pt.setY(pt.y() - ascent);
if (hasShadow) {
p->save();
p->setPen(QColor(shadowColor));
p->translate(shadowSize.width(), shadowSize.height());
line.draw(p, pt);
p->restore();
}
p->setPen(textFillPen);
line.draw(p, pt);
p->restore();
return;
}
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping);
pt.setX(pt.x() + skipWidth);
string = fromRawDataWithoutRef(sanitized, from, to - from);
#endif
}
p->setFont(font);
int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
// See QWebPagePrivate::QWebPagePrivate() where the default path is set to Complex for Qt 4.6 and earlier.
if (!isComplexText)
//.........这里部分代码省略.........
示例8: generateComponents
static int generateComponents(TextRunComponents* components, const Font &font, const TextRun &run)
{
int letterSpacing = font.letterSpacing();
int wordSpacing = font.wordSpacing();
int padding = run.padding();
int numSpaces = 0;
if (padding) {
for (int i = 0; i < run.length(); i++)
if (Font::treatAsSpace(run[i]))
++numSpaces;
}
int offset = 0;
if (letterSpacing) {
// need to draw every letter on it's own
int start = 0;
if (Font::treatAsSpace(run[0])) {
int add = 0;
if (numSpaces) {
add = padding/numSpaces;
padding -= add;
--numSpaces;
}
components->append(TextRunComponent(1, font, offset));
offset += add + letterSpacing + components->last().m_width;
start = 1;
}
for (int i = 1; i < run.length(); ++i) {
uint ch = run[i];
if (isHighSurrogate(ch) && isLowSurrogate(run[i-1]))
ch = surrogateToUcs4(ch, run[i-1]);
if (isLowSurrogate(ch) || category(ch) == Mark_NonSpacing)
continue;
if (Font::treatAsSpace(run[i])) {
int add = 0;
if (i - start > 0) {
components->append(TextRunComponent(run.characters() + start, i - start,
run, font, offset));
offset += components->last().m_width + letterSpacing;
}
if (numSpaces) {
add = padding/numSpaces;
padding -= add;
--numSpaces;
}
components->append(TextRunComponent(1, font, offset));
offset += wordSpacing + add + components->last().m_width + letterSpacing;
start = i + 1;
continue;
}
if (i - start > 0) {
components->append(TextRunComponent(run.characters() + start, i - start,
run,
font, offset));
offset += components->last().m_width + letterSpacing;
}
start = i;
}
if (run.length() - start > 0) {
components->append(TextRunComponent(run.characters() + start, run.length() - start,
run,
font, offset));
offset += components->last().m_width;
}
offset += letterSpacing;
} else {
int start = 0;
for (int i = 0; i < run.length(); ++i) {
if (Font::treatAsSpace(run[i])) {
if (i - start > 0) {
components->append(TextRunComponent(run.characters() + start, i - start,
run,
font, offset));
offset += components->last().m_width;
}
int add = 0;
if (numSpaces) {
add = padding/numSpaces;
padding -= add;
--numSpaces;
}
components->append(TextRunComponent(1, font, offset));
offset += add + components->last().m_width;
if (i)
offset += wordSpacing;
start = i + 1;
}
}
if (run.length() - start > 0) {
components->append(TextRunComponent(run.characters() + start, run.length() - start,
run,
font, offset));
offset += components->last().m_width;
}
}
return offset;
}
示例9: codePath
Font::CodePath Font::codePath(const TextRun& run) const
{
if (s_codePath != Auto)
return s_codePath;
#if PLATFORM(QT) && !HAVE(QRAWFONT)
if (run.expansion() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing())
return Complex;
#endif
CodePath result = Simple;
// Start from 0 since drawing and highlighting also measure the characters before run->from
// FIXME: Should use a UnicodeSet in ports where ICU is used. Note that we
// can't simply use UnicodeCharacter Property/class because some characters
// are not 'combining', but still need to go to the complex path.
// Alternatively, we may as well consider binary search over a sorted
// list of ranges.
for (int i = 0; i < run.length(); i++) {
const UChar c = run[i];
if (c < 0x2E5) // U+02E5 through U+02E9 (Modifier Letters : Tone letters)
continue;
if (c <= 0x2E9)
return Complex;
if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
continue;
if (c <= 0x36F)
return Complex;
if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
continue;
if (c <= 0x05CF)
return Complex;
// U+0600 through U+109F Arabic, Syriac, Thaana, NKo, Samaritan, Mandaic,
// Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada,
// Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
if (c < 0x0600)
continue;
if (c <= 0x109F)
return Complex;
// U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose;
// Modern Korean will be precomposed as a result of step A)
if (c < 0x1100)
continue;
if (c <= 0x11FF)
return Complex;
if (c < 0x135D) // U+135D through U+135F Ethiopic combining marks
continue;
if (c <= 0x135F)
return Complex;
if (c < 0x1700) // U+1780 through U+18AF Tagalog, Hanunoo, Buhid, Taghanwa,Khmer, Mongolian
continue;
if (c <= 0x18AF)
return Complex;
if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
continue;
if (c <= 0x194F)
return Complex;
if (c < 0x1980) // U+1980 through U+19DF New Tai Lue
continue;
if (c <= 0x19DF)
return Complex;
if (c < 0x1A00) // U+1A00 through U+1CFF Buginese, Tai Tham, Balinese, Batak, Lepcha, Vedic
continue;
if (c <= 0x1CFF)
return Complex;
if (c < 0x1DC0) // U+1DC0 through U+1DFF Comining diacritical mark supplement
continue;
if (c <= 0x1DFF)
return Complex;
// U+1E00 through U+2000 characters with diacritics and stacked diacritics
if (c <= 0x2000) {
result = SimpleWithGlyphOverflow;
continue;
}
if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
continue;
if (c <= 0x20FF)
return Complex;
if (c < 0x2CEF) // U+2CEF through U+2CF1 Combining marks for Coptic
continue;
if (c <= 0x2CF1)
return Complex;
if (c < 0x302A) // U+302A through U+302F Ideographic and Hangul Tone marks
continue;
if (c <= 0x302F)
return Complex;
//.........这里部分代码省略.........
示例10: floatWidthForComplexText
float Font::floatWidthForComplexText(const TextRun& run, const TextStyle&) const
{
// FIXME: style
QFontMetricsF metrics(primaryFont()->m_font.font());
return metrics.width(QString::fromRawData(reinterpret_cast<const QChar*>(run.characters() + run.from()), run.length()));
}
示例11: drawComplexText
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
cairo_t* cr = context->platformContext();
cairo_save(cr);
cairo_translate(cr, point.x(), point.y());
PangoLayout* layout = pango_cairo_create_layout(cr);
setPangoAttributes(this, run, layout);
gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
pango_layout_set_text(layout, utf8, -1);
// Our layouts are single line
PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0);
GdkRegion* partialRegion = NULL;
if (to - from != run.length()) {
// Clip the region of the run to be rendered
char* start = g_utf8_offset_to_pointer(utf8, from);
char* end = g_utf8_offset_to_pointer(start, to - from);
int ranges[] = {start - utf8, end - utf8};
partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1);
gdk_region_shrink(partialRegion, 0, -pixelSize());
}
Color fillColor = context->fillColor();
float red, green, blue, alpha;
// Text shadow, inspired by FontMac
IntSize shadowSize;
int shadowBlur = 0;
Color shadowColor;
bool hasShadow = context->textDrawingMode() == cTextFill &&
context->getShadow(shadowSize, shadowBlur, shadowColor);
// TODO: Blur support
if (hasShadow) {
// Disable graphics context shadows (not yet implemented) and paint them manually
context->clearShadow();
Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
cairo_save(cr);
shadowFillColor.getRGBA(red, green, blue, alpha);
cairo_set_source_rgba(cr, red, green, blue, alpha);
cairo_translate(cr, shadowSize.width(), shadowSize.height());
if (partialRegion) {
gdk_cairo_region(cr, partialRegion);
cairo_clip(cr);
}
pango_cairo_show_layout_line(cr, layoutLine);
cairo_restore(cr);
}
fillColor.getRGBA(red, green, blue, alpha);
cairo_set_source_rgba(cr, red, green, blue, alpha);
if (partialRegion) {
gdk_cairo_region(cr, partialRegion);
cairo_clip(cr);
}
pango_cairo_show_layout_line(cr, layoutLine);
if (context->textDrawingMode() & cTextStroke) {
Color strokeColor = context->strokeColor();
strokeColor.getRGBA(red, green, blue, alpha);
cairo_set_source_rgba(cr, red, green, blue, alpha);
pango_cairo_layout_line_path(cr, layoutLine);
cairo_set_line_width(cr, context->strokeThickness());
cairo_stroke(cr);
}
// Re-enable the platform shadow we disabled earlier
if (hasShadow)
context->setShadow(shadowSize, shadowBlur, shadowColor);
// Pango sometimes leaves behind paths we don't want
cairo_new_path(cr);
if (partialRegion)
gdk_region_destroy(partialRegion);
g_free(utf8);
g_object_unref(layout);
cairo_restore(cr);
}
示例12: floatWidthForComplexText
float Font::floatWidthForComplexText(const TextRun& run, const TextStyle& style) const
{
UniscribeController controller(this, run, style);
controller.advance(run.length());
return controller.runWidthSoFar();
}
示例13: drawSimpleText
// SDL ttf implementation may be lighter ???
void Font::drawSimpleText(BIGraphicsContext* context, const TextRun& run, const TextStyle& style, const FloatPoint& point) const
{
WebCore::Color text_color = context->strokeColor();
BINativeImage* text_surface;
IntRect dst_rect;
IntPoint intPoint;
static int oldx = 0;
int text_width, text_height;
bool init = false;
int numSpaces = 0;
int padPerSpace = 0;
FloatPoint wordPoint(point);
// Process normal, bold, italic styles
if (m_fontDescription.italic()) {
if (m_fontDescription.bold()) {
// Bold && italic
d->m_ttfFont->style = FT_STYLE_BOLD | FT_STYLE_ITALIC;
d->flushCache(d->m_ttfFont);
} else {
// Only italic
d->m_ttfFont->style = FT_STYLE_ITALIC;
d->flushCache(d->m_ttfFont);
}
} else if (m_fontDescription.bold()) {
// Only bold
d->m_ttfFont->style = FT_STYLE_BOLD;
d->flushCache(d->m_ttfFont);
} else {
d->m_ttfFont->style = FT_STYLE_NORMAL;
d->flushCache(d->m_ttfFont);
}
// Draw font
int wordSize = run.length() - run.from();
UChar word[wordSize];
copyTextRunTo(run, word);
for (int i = 0; i <= wordSize; i++) {
if (Font::treatAsSpace(word[i]))
numSpaces++;;
}
if (numSpaces == 0)
padPerSpace = 0;
else
padPerSpace = static_cast<int> (ceil(style.padding() / numSpaces));
UChar text[wordSize + 1];
int j = 0;
for (int i = 0; i <= wordSize; i++) {
if (Font::treatAsSpace(word[i]) || i == wordSize) {
text[j] = ' ';
text[++j] = '\0';
d->sizeUnicode(d->m_ttfFont, text, &text_width, &text_height);
text_surface = d->renderUnicodeBlended(d->m_ttfFont, text, text_color, context->alphaLayer());
if (text_surface) {
intPoint.setX(static_cast<uint16_t> (wordPoint.x()));
intPoint.setY(static_cast<uint16_t> (wordPoint.y()) - ascent());
dst_rect.setX(0);
dst_rect.setY(0);
dst_rect.setWidth(text_surface->size().width());
dst_rect.setHeight(text_surface->size().height());
getBIGraphicsDevice()->copy(*(context->widget()), *text_surface, dst_rect, intPoint, context->alphaLayer());
delete text_surface;
}
wordPoint = wordPoint + FloatSize(padPerSpace + text_width,0);
j = 0;
} else {
text[j] = word[i];
j++;
}
}
}
示例14: drawComplexText
void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
{
if (to < 0)
to = run.length();
QPainter *p = ctx->platformContext();
Color color = ctx->fillColor();
p->setPen(QColor(color));
QString string = qstring(run);
// text shadow
IntSize shadowSize;
int shadowBlur;
Color shadowColor;
bool hasShadow = ctx->textDrawingMode() == cTextFill && ctx->getShadow(shadowSize, shadowBlur, shadowColor);
if (from > 0 || to < run.length()) {
QTextLayout layout(string, font());
QTextLine line = setupLayout(&layout, run);
float x1 = line.cursorToX(from);
float x2 = line.cursorToX(to);
if (x2 < x1)
qSwap(x1, x2);
QFontMetrics fm(font());
int ascent = fm.ascent();
QRectF clip(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
if (hasShadow) {
// TODO: when blur support is added, the clip will need to account
// for the blur radius
qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
if (shadowSize.width() > 0)
dx2 = shadowSize.width();
else
dx1 = -shadowSize.width();
if (shadowSize.height() > 0)
dy2 = shadowSize.height();
else
dy1 = -shadowSize.height();
// expand the clip rect to include the text shadow as well
clip.adjust(dx1, dx2, dy1, dy2);
}
p->save();
p->setClipRect(clip.toRect());
QPointF pt(point.x(), point.y() - ascent);
if (hasShadow) {
p->save();
p->setPen(QColor(shadowColor));
p->translate(shadowSize.width(), shadowSize.height());
line.draw(p, pt);
p->restore();
}
line.draw(p, pt);
p->restore();
return;
}
p->setFont(font());
QPointF pt(point.x(), point.y());
int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
if (hasShadow) {
// TODO: text shadow blur support
p->save();
p->setPen(QColor(shadowColor));
p->translate(shadowSize.width(), shadowSize.height());
p->drawText(pt, string, flags, run.padding());
p->restore();
}
p->drawText(pt, string, flags, run.padding());
}
示例15: drawTextCommon
static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to, const QFont& font, bool isComplexText)
{
if (to < 0)
to = run.length();
QPainter *p = ctx->platformContext();
QPen textFillPen;
if (ctx->textDrawingMode() & TextModeFill) {
if (ctx->fillGradient()) {
QBrush brush(*ctx->fillGradient()->platformGradient());
brush.setTransform(ctx->fillGradient()->gradientSpaceTransform());
textFillPen = QPen(brush, 0);
} else if (ctx->fillPattern()) {
AffineTransform affine;
textFillPen = QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0);
} else
textFillPen = QPen(QColor(ctx->fillColor()));
}
QPen textStrokePen;
if (ctx->textDrawingMode() & TextModeStroke) {
if (ctx->strokeGradient()) {
QBrush brush(*ctx->strokeGradient()->platformGradient());
brush.setTransform(ctx->strokeGradient()->gradientSpaceTransform());
textStrokePen = QPen(brush, ctx->strokeThickness());
} else if (ctx->strokePattern()) {
AffineTransform affine;
QBrush brush(ctx->strokePattern()->createPlatformPattern(affine));
textStrokePen = QPen(brush, ctx->strokeThickness());
} else
textStrokePen = QPen(QColor(ctx->strokeColor()), ctx->strokeThickness());
}
String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
QString string = fromRawDataWithoutRef(sanitized);
QPointF pt(point.x(), point.y());
if (from > 0 || to < run.length()) {
if (isComplexText) {
QTextLayout layout(string, font);
QTextLine line = setupLayout(&layout, run);
float x1 = line.cursorToX(from);
float x2 = line.cursorToX(to);
if (x2 < x1)
qSwap(x1, x2);
QFontMetrics fm(font);
int ascent = fm.ascent();
QRectF boundingRect(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
QRectF clip = boundingRect;
ContextShadow* ctxShadow = ctx->contextShadow();
if (ctxShadow->m_type != ContextShadow::NoShadow) {
qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
if (ctxShadow->offset().x() > 0)
dx2 = ctxShadow->offset().x();
else
dx1 = -ctxShadow->offset().x();
if (ctxShadow->offset().y() > 0)
dy2 = ctxShadow->offset().y();
else
dy1 = -ctxShadow->offset().y();
// expand the clip rect to include the text shadow as well
clip.adjust(dx1, dx2, dy1, dy2);
clip.adjust(-ctxShadow->m_blurDistance, -ctxShadow->m_blurDistance, ctxShadow->m_blurDistance, ctxShadow->m_blurDistance);
}
p->save();
p->setClipRect(clip.toRect(), Qt::IntersectClip);
pt.setY(pt.y() - ascent);
if (ctxShadow->m_type != ContextShadow::NoShadow) {
ContextShadow* ctxShadow = ctx->contextShadow();
if (!ctxShadow->mustUseContextShadow(p)) {
p->save();
p->setPen(ctxShadow->m_color);
p->translate(ctxShadow->offset());
line.draw(p, pt);
p->restore();
} else {
QPainter* shadowPainter = ctxShadow->beginShadowLayer(p, boundingRect);
if (shadowPainter) {
// Since it will be blurred anyway, we don't care about render hints.
shadowPainter->setFont(p->font());
shadowPainter->setPen(ctxShadow->m_color);
line.draw(shadowPainter, pt);
ctxShadow->endShadowLayer(p);
}
}
}
p->setPen(textFillPen);
line.draw(p, pt);
p->restore();
return;
}
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping);
pt.setX(pt.x() + skipWidth);
string = fromRawDataWithoutRef(sanitized, from, to - from);
//.........这里部分代码省略.........