mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 502906 - part 4 - refactor DWrite font code to match Mac and GDI structure. r=bas
This commit is contained in:
parent
76b1730341
commit
b81c24c7fb
@ -67,9 +67,9 @@ public:
|
||||
|
||||
gfxFloat GetAdjustedSize() const { return mAdjustedSize; }
|
||||
|
||||
protected:
|
||||
friend class gfxDWriteFontGroup;
|
||||
IDWriteFontFace *GetFontFace() { return mFontFace.get(); }
|
||||
|
||||
protected:
|
||||
void ComputeMetrics();
|
||||
|
||||
cairo_font_face_t *CairoFontFace();
|
||||
@ -85,32 +85,4 @@ protected:
|
||||
PRBool mNeedsOblique;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing a DWrite windows font group.
|
||||
*/
|
||||
class gfxDWriteFontGroup : public gfxFontGroup
|
||||
{
|
||||
public:
|
||||
gfxDWriteFontGroup(const nsAString& aFamilies,
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet);
|
||||
virtual ~gfxDWriteFontGroup();
|
||||
|
||||
gfxFontGroup *Copy(const gfxFontStyle *aStyle);
|
||||
|
||||
/**
|
||||
* Gets the font at a certain position in the font list, it will
|
||||
* create this font if it hasn't actually been created yet.
|
||||
*
|
||||
* \param i Position in the font list
|
||||
* \return Object representing the font
|
||||
*/
|
||||
virtual gfxDWriteFont *GetFontAt(PRInt32 i);
|
||||
|
||||
virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
const Parameters *aParams, PRUint32 aFlags);
|
||||
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||
const Parameters *aParams, PRUint32 aFlags);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -71,6 +71,7 @@ OS_LIBS += $(call EXPAND_LIBNAME,ddraw)
|
||||
else
|
||||
ifdef MOZ_ENABLE_DWRITE_FONT
|
||||
CPPSRCS += gfxDWriteFonts.cpp \
|
||||
gfxDWriteShaper.cpp \
|
||||
gfxDWriteTextAnalysis.cpp \
|
||||
gfxDWriteCommon.cpp \
|
||||
gfxD2DSurface.cpp \
|
||||
|
@ -36,6 +36,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "gfxDWriteFonts.h"
|
||||
#include "gfxDWriteShaper.h"
|
||||
#include "gfxDWriteFontList.h"
|
||||
#include "gfxContext.h"
|
||||
#include <dwrite.h>
|
||||
@ -80,6 +81,8 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
|
||||
}
|
||||
|
||||
ComputeMetrics();
|
||||
|
||||
mShaper = new gfxDWriteShaper(this);
|
||||
}
|
||||
|
||||
gfxDWriteFont::~gfxDWriteFont()
|
||||
@ -278,278 +281,3 @@ gfxDWriteFont::CairoScaledFont()
|
||||
|
||||
return mCairoScaledFont;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// gfxDWriteFontGroup
|
||||
gfxDWriteFontGroup::gfxDWriteFontGroup(const nsAString& aFamilies,
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
: gfxFontGroup(aFamilies, aStyle, aUserFontSet)
|
||||
{
|
||||
}
|
||||
|
||||
gfxDWriteFontGroup::~gfxDWriteFontGroup()
|
||||
{
|
||||
}
|
||||
|
||||
gfxDWriteFont *
|
||||
gfxDWriteFontGroup::GetFontAt(PRInt32 i)
|
||||
{
|
||||
// If it turns out to be hard for all clients that cache font
|
||||
// groups to call UpdateFontList at appropriate times, we could
|
||||
// instead consider just calling UpdateFontList from someplace
|
||||
// more central (such as here).
|
||||
NS_ASSERTION(!mUserFontSet || mCurrGeneration == GetGeneration(),
|
||||
"Whoever was caching this font group should have "
|
||||
"called UpdateFontList on it");
|
||||
NS_ASSERTION(mFonts.Length() > PRUint32(i),
|
||||
"Requesting a font index that doesn't exist");
|
||||
|
||||
return static_cast<gfxDWriteFont*>(mFonts[i].get());
|
||||
}
|
||||
|
||||
gfxFontGroup *
|
||||
gfxDWriteFontGroup::Copy(const gfxFontStyle *aStyle)
|
||||
{
|
||||
return new gfxDWriteFontGroup(mFamilies, aStyle, mUserFontSet);
|
||||
}
|
||||
|
||||
#define MAX_RANGE_LENGTH 25000
|
||||
gfxTextRun *
|
||||
gfxDWriteFontGroup::MakeTextRun(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
const Parameters *aParams,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
HRESULT hr;
|
||||
// TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
|
||||
|
||||
gfxTextRun *textRun = gfxTextRun::Create(aParams,
|
||||
aString,
|
||||
aLength,
|
||||
this,
|
||||
aFlags);
|
||||
|
||||
gfxPlatform::GetPlatform()->SetupClusterBoundaries(textRun, aString);
|
||||
|
||||
DWRITE_READING_DIRECTION readingDirection =
|
||||
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
|
||||
if (textRun->IsRightToLeft()) {
|
||||
readingDirection = DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;
|
||||
}
|
||||
nsRefPtr<gfxDWriteFont> font = GetFontAt(0);
|
||||
|
||||
textRun->AddGlyphRun(font, 0);
|
||||
gfxTextRun::CompressedGlyph g;
|
||||
|
||||
nsRefPtr<IDWriteTextAnalyzer> analyzer;
|
||||
|
||||
hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateTextAnalyzer(getter_AddRefs(analyzer));
|
||||
|
||||
nsTArray<gfxTextRange> ranges;
|
||||
|
||||
ComputeRanges(ranges, aString, 0, aLength);
|
||||
|
||||
/**
|
||||
* There's an internal 16-bit limit on some things inside the analyzer.
|
||||
* to be on the safe side here we split up any ranges over MAX_RANGE_LENGTH
|
||||
* characters.
|
||||
* TODO: Figure out what exactly is going on, and what is a safe number, and
|
||||
* why.
|
||||
* TODO: Figure out good places to split this.
|
||||
*/
|
||||
for (unsigned int i = 0; i < ranges.Length(); i++) {
|
||||
if (ranges[i].Length() > MAX_RANGE_LENGTH) {
|
||||
ranges.InsertElementAt(i + 1,
|
||||
gfxTextRange(ranges[i].start
|
||||
+ MAX_RANGE_LENGTH,
|
||||
ranges[i].end));
|
||||
ranges[i + 1].font = ranges[i].font;
|
||||
ranges[i].end = ranges[i].start + MAX_RANGE_LENGTH;
|
||||
}
|
||||
}
|
||||
UINT32 rangeOffset = 0;
|
||||
for (unsigned int i = 0; i < ranges.Length(); i++) {
|
||||
gfxTextRange &range = ranges[i];
|
||||
TextAnalysis analysis(
|
||||
aString + range.start, range.Length(),
|
||||
NULL,
|
||||
readingDirection);
|
||||
TextAnalysis::Run *runHead;
|
||||
DWRITE_LINE_BREAKPOINT *linebreaks;
|
||||
hr = analysis.GenerateResults(analyzer, &runHead, &linebreaks);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Analyzer failed to generate results.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (range.font) {
|
||||
font = static_cast<gfxDWriteFont*>(range.font.get());
|
||||
} else {
|
||||
// XXX missing glyph info needs to be set
|
||||
font = GetFontAt(0);
|
||||
}
|
||||
|
||||
textRun->AddGlyphRun(font, range.start);
|
||||
|
||||
PRUint32 appUnitsPerDevPixel = textRun->GetAppUnitsPerDevUnit();
|
||||
|
||||
UINT32 maxGlyphs = 0;
|
||||
trymoreglyphs:
|
||||
if ((PR_UINT32_MAX - 3 * range.Length() / 2 + 16) < maxGlyphs) {
|
||||
// This isn't going to work, we're going to cross the UINT32 upper
|
||||
// limit. Next range it is.
|
||||
continue;
|
||||
}
|
||||
maxGlyphs += 3 * range.Length() / 2 + 16;
|
||||
|
||||
nsAutoTArray<UINT16, 400> clusters;
|
||||
nsAutoTArray<UINT16, 400> indices;
|
||||
nsAutoTArray<DWRITE_SHAPING_TEXT_PROPERTIES, 400> textProperties;
|
||||
nsAutoTArray<DWRITE_SHAPING_GLYPH_PROPERTIES, 400> glyphProperties;
|
||||
if (!clusters.SetLength(range.Length()) ||
|
||||
!indices.SetLength(maxGlyphs) ||
|
||||
!textProperties.SetLength(maxGlyphs) ||
|
||||
!glyphProperties.SetLength(maxGlyphs)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UINT32 actualGlyphs;
|
||||
|
||||
hr = analyzer->GetGlyphs(aString + range.start, range.Length(),
|
||||
font->mFontFace, FALSE,
|
||||
readingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT,
|
||||
&runHead->mScript, NULL, NULL, NULL, NULL, 0,
|
||||
maxGlyphs, clusters.Elements(), textProperties.Elements(),
|
||||
indices.Elements(), glyphProperties.Elements(), &actualGlyphs);
|
||||
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
|
||||
// We increase the amount of glyphs and try again.
|
||||
goto trymoreglyphs;
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Analyzer failed to get glyphs.");
|
||||
continue;
|
||||
}
|
||||
|
||||
WORD gID = indices[0];
|
||||
nsAutoTArray<FLOAT, 400> advances;
|
||||
nsAutoTArray<DWRITE_GLYPH_OFFSET, 400> glyphOffsets;
|
||||
if (!advances.SetLength(actualGlyphs) ||
|
||||
!glyphOffsets.SetLength(actualGlyphs)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hr = analyzer->GetGlyphPlacements(aString + range.start,
|
||||
clusters.Elements(),
|
||||
textProperties.Elements(),
|
||||
range.Length(),
|
||||
indices.Elements(),
|
||||
glyphProperties.Elements(),
|
||||
actualGlyphs,
|
||||
font->mFontFace,
|
||||
(float)font->GetAdjustedSize(),
|
||||
FALSE,
|
||||
FALSE,
|
||||
&runHead->mScript,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
advances.Elements(),
|
||||
glyphOffsets.Elements());
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Analyzer failed to get glyph placements.");
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoTArray<gfxTextRun::DetailedGlyph,1> detailedGlyphs;
|
||||
|
||||
for (unsigned int c = 0; c < range.Length(); c++) {
|
||||
PRUint32 k = clusters[c];
|
||||
PRUint32 absC = range.start + c;
|
||||
|
||||
if (c > 0 && k == clusters[c - 1]) {
|
||||
g.SetComplex(textRun->IsClusterStart(absC), PR_FALSE, 0);
|
||||
textRun->SetGlyphs(absC, g, nsnull);
|
||||
// This is a cluster continuation. No glyph here.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Count glyphs for this character
|
||||
PRUint32 glyphCount = actualGlyphs - k;
|
||||
PRUint32 nextClusterOffset;
|
||||
for (nextClusterOffset = c + 1;
|
||||
nextClusterOffset < range.Length(); ++nextClusterOffset) {
|
||||
if (clusters[nextClusterOffset] > k) {
|
||||
glyphCount = clusters[nextClusterOffset] - k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PRInt32 advance =
|
||||
(PRInt32)(advances[k] * aParams->mAppUnitsPerDevUnit);
|
||||
if (glyphCount == 1 && advance >= 0 &&
|
||||
glyphOffsets[k].advanceOffset == 0 &&
|
||||
glyphOffsets[k].ascenderOffset == 0 &&
|
||||
textRun->IsClusterStart(absC) &&
|
||||
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
|
||||
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(indices[k])) {
|
||||
textRun->SetSimpleGlyph(absC,
|
||||
g.SetSimpleGlyph(advance,
|
||||
indices[k]));
|
||||
} else {
|
||||
if (detailedGlyphs.Length() < glyphCount) {
|
||||
if (!detailedGlyphs.AppendElements(
|
||||
glyphCount - detailedGlyphs.Length())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
float totalAdvance = 0;
|
||||
for (unsigned int z = 0; z < glyphCount; z++) {
|
||||
detailedGlyphs[z].mGlyphID = indices[k + z];
|
||||
detailedGlyphs[z].mAdvance =
|
||||
(PRInt32)(advances[k + z]
|
||||
* aParams->mAppUnitsPerDevUnit);
|
||||
if (readingDirection ==
|
||||
DWRITE_READING_DIRECTION_RIGHT_TO_LEFT) {
|
||||
detailedGlyphs[z].mXOffset =
|
||||
(totalAdvance +
|
||||
glyphOffsets[k + z].advanceOffset)
|
||||
* aParams->mAppUnitsPerDevUnit;
|
||||
} else {
|
||||
detailedGlyphs[z].mXOffset =
|
||||
glyphOffsets[k + z].advanceOffset *
|
||||
aParams->mAppUnitsPerDevUnit;
|
||||
}
|
||||
detailedGlyphs[z].mYOffset =
|
||||
-glyphOffsets[k + z].ascenderOffset *
|
||||
aParams->mAppUnitsPerDevUnit;
|
||||
totalAdvance += advances[k + z];
|
||||
}
|
||||
textRun->SetGlyphs(
|
||||
absC,
|
||||
g.SetComplex(textRun->IsClusterStart(absC),
|
||||
PR_TRUE,
|
||||
glyphCount),
|
||||
detailedGlyphs.Elements());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return textRun;
|
||||
}
|
||||
|
||||
gfxTextRun *
|
||||
gfxDWriteFontGroup::MakeTextRun(const PRUint8 *aString,
|
||||
PRUint32 aLength,
|
||||
const Parameters *aParams,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
nsCString string((const char*)aString, aLength);
|
||||
return MakeTextRun(NS_ConvertASCIItoUTF16(string).get(),
|
||||
aLength,
|
||||
aParams,
|
||||
aFlags);
|
||||
}
|
||||
|
261
gfx/thebes/src/gfxDWriteShaper.cpp
Normal file
261
gfx/thebes/src/gfxDWriteShaper.cpp
Normal file
@ -0,0 +1,261 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Foundation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "gfxDWriteShaper.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
|
||||
#include <dwrite.h>
|
||||
|
||||
#include "gfxDWriteTextAnalysis.h"
|
||||
|
||||
|
||||
#define MAX_RANGE_LENGTH 25000
|
||||
|
||||
PRBool
|
||||
gfxDWriteShaper::InitTextRun(gfxContext *aContext,
|
||||
gfxTextRun *aTextRun,
|
||||
const PRUnichar *aString,
|
||||
PRUint32 aRunStart,
|
||||
PRUint32 aRunLength)
|
||||
{
|
||||
HRESULT hr;
|
||||
// TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
|
||||
|
||||
DWRITE_READING_DIRECTION readingDirection =
|
||||
aTextRun->IsRightToLeft()
|
||||
? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
|
||||
: DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
|
||||
|
||||
gfxDWriteFont *font = static_cast<gfxDWriteFont*>(mFont);
|
||||
|
||||
gfxTextRun::CompressedGlyph g;
|
||||
|
||||
nsRefPtr<IDWriteTextAnalyzer> analyzer;
|
||||
|
||||
hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateTextAnalyzer(getter_AddRefs(analyzer));
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* There's an internal 16-bit limit on some things inside the analyzer.
|
||||
* to be on the safe side here we split up any ranges over MAX_RANGE_LENGTH
|
||||
* characters.
|
||||
* TODO: Figure out what exactly is going on, and what is a safe number, and
|
||||
* why.
|
||||
* TODO: Figure out good places to split this.
|
||||
*/
|
||||
/*
|
||||
for (unsigned int i = 0; i < ranges.Length(); i++) {
|
||||
if (ranges[i].Length() > MAX_RANGE_LENGTH) {
|
||||
ranges.InsertElementAt(i + 1,
|
||||
gfxTextRange(ranges[i].start
|
||||
+ MAX_RANGE_LENGTH,
|
||||
ranges[i].end));
|
||||
ranges[i + 1].font = ranges[i].font;
|
||||
ranges[i].end = ranges[i].start + MAX_RANGE_LENGTH;
|
||||
}
|
||||
}
|
||||
UINT32 rangeOffset = 0;
|
||||
*/
|
||||
// for (unsigned int i = 0; i < ranges.Length(); i++) {
|
||||
// gfxTextRange &range = ranges[i];
|
||||
PRBool result = PR_TRUE;
|
||||
do {
|
||||
gfxTextRange range(aRunStart, aRunStart + aRunLength);
|
||||
TextAnalysis analysis(
|
||||
aString + range.start, range.Length(),
|
||||
NULL,
|
||||
readingDirection);
|
||||
TextAnalysis::Run *runHead;
|
||||
DWRITE_LINE_BREAKPOINT *linebreaks;
|
||||
hr = analysis.GenerateResults(analyzer, &runHead, &linebreaks);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Analyzer failed to generate results.");
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
PRUint32 appUnitsPerDevPixel = aTextRun->GetAppUnitsPerDevUnit();
|
||||
|
||||
UINT32 maxGlyphs = 0;
|
||||
trymoreglyphs:
|
||||
if ((PR_UINT32_MAX - 3 * range.Length() / 2 + 16) < maxGlyphs) {
|
||||
// This isn't going to work, we're going to cross the UINT32 upper
|
||||
// limit. Next range it is.
|
||||
continue;
|
||||
}
|
||||
maxGlyphs += 3 * range.Length() / 2 + 16;
|
||||
|
||||
nsAutoTArray<UINT16, 400> clusters;
|
||||
nsAutoTArray<UINT16, 400> indices;
|
||||
nsAutoTArray<DWRITE_SHAPING_TEXT_PROPERTIES, 400> textProperties;
|
||||
nsAutoTArray<DWRITE_SHAPING_GLYPH_PROPERTIES, 400> glyphProperties;
|
||||
if (!clusters.SetLength(range.Length()) ||
|
||||
!indices.SetLength(maxGlyphs) ||
|
||||
!textProperties.SetLength(maxGlyphs) ||
|
||||
!glyphProperties.SetLength(maxGlyphs)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UINT32 actualGlyphs;
|
||||
|
||||
hr = analyzer->GetGlyphs(aString + range.start, range.Length(),
|
||||
font->GetFontFace(), FALSE,
|
||||
readingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT,
|
||||
&runHead->mScript, NULL, NULL, NULL, NULL, 0,
|
||||
maxGlyphs, clusters.Elements(), textProperties.Elements(),
|
||||
indices.Elements(), glyphProperties.Elements(), &actualGlyphs);
|
||||
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
|
||||
// We increase the amount of glyphs and try again.
|
||||
goto trymoreglyphs;
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Analyzer failed to get glyphs.");
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
WORD gID = indices[0];
|
||||
nsAutoTArray<FLOAT, 400> advances;
|
||||
nsAutoTArray<DWRITE_GLYPH_OFFSET, 400> glyphOffsets;
|
||||
if (!advances.SetLength(actualGlyphs) ||
|
||||
!glyphOffsets.SetLength(actualGlyphs)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hr = analyzer->GetGlyphPlacements(aString + range.start,
|
||||
clusters.Elements(),
|
||||
textProperties.Elements(),
|
||||
range.Length(),
|
||||
indices.Elements(),
|
||||
glyphProperties.Elements(),
|
||||
actualGlyphs,
|
||||
font->GetFontFace(),
|
||||
font->GetAdjustedSize(),
|
||||
FALSE,
|
||||
FALSE,
|
||||
&runHead->mScript,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
advances.Elements(),
|
||||
glyphOffsets.Elements());
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Analyzer failed to get glyph placements.");
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoTArray<gfxTextRun::DetailedGlyph,1> detailedGlyphs;
|
||||
|
||||
for (unsigned int c = 0; c < range.Length(); c++) {
|
||||
PRUint32 k = clusters[c];
|
||||
PRUint32 absC = range.start + c;
|
||||
|
||||
if (c > 0 && k == clusters[c - 1]) {
|
||||
g.SetComplex(aTextRun->IsClusterStart(absC), PR_FALSE, 0);
|
||||
aTextRun->SetGlyphs(absC, g, nsnull);
|
||||
// This is a cluster continuation. No glyph here.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Count glyphs for this character
|
||||
PRUint32 glyphCount = actualGlyphs - k;
|
||||
PRUint32 nextClusterOffset;
|
||||
for (nextClusterOffset = c + 1;
|
||||
nextClusterOffset < range.Length(); ++nextClusterOffset) {
|
||||
if (clusters[nextClusterOffset] > k) {
|
||||
glyphCount = clusters[nextClusterOffset] - k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PRInt32 advance = (PRInt32)(advances[k] * appUnitsPerDevPixel);
|
||||
if (glyphCount == 1 && advance >= 0 &&
|
||||
glyphOffsets[k].advanceOffset == 0 &&
|
||||
glyphOffsets[k].ascenderOffset == 0 &&
|
||||
aTextRun->IsClusterStart(absC) &&
|
||||
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
|
||||
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(indices[k])) {
|
||||
aTextRun->SetSimpleGlyph(absC,
|
||||
g.SetSimpleGlyph(advance,
|
||||
indices[k]));
|
||||
} else {
|
||||
if (detailedGlyphs.Length() < glyphCount) {
|
||||
if (!detailedGlyphs.AppendElements(
|
||||
glyphCount - detailedGlyphs.Length())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
float totalAdvance = 0;
|
||||
for (unsigned int z = 0; z < glyphCount; z++) {
|
||||
detailedGlyphs[z].mGlyphID = indices[k + z];
|
||||
detailedGlyphs[z].mAdvance =
|
||||
(PRInt32)(advances[k + z]
|
||||
* appUnitsPerDevPixel);
|
||||
if (readingDirection ==
|
||||
DWRITE_READING_DIRECTION_RIGHT_TO_LEFT) {
|
||||
detailedGlyphs[z].mXOffset =
|
||||
(totalAdvance +
|
||||
glyphOffsets[k + z].advanceOffset)
|
||||
* appUnitsPerDevPixel;
|
||||
} else {
|
||||
detailedGlyphs[z].mXOffset =
|
||||
glyphOffsets[k + z].advanceOffset *
|
||||
appUnitsPerDevPixel;
|
||||
}
|
||||
detailedGlyphs[z].mYOffset =
|
||||
-glyphOffsets[k + z].ascenderOffset *
|
||||
appUnitsPerDevPixel;
|
||||
totalAdvance += advances[k + z];
|
||||
}
|
||||
aTextRun->SetGlyphs(
|
||||
absC,
|
||||
g.SetComplex(aTextRun->IsClusterStart(absC),
|
||||
PR_TRUE,
|
||||
glyphCount),
|
||||
detailedGlyphs.Elements());
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return result;
|
||||
}
|
62
gfx/thebes/src/gfxDWriteShaper.h
Normal file
62
gfx/thebes/src/gfxDWriteShaper.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Foundation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef GFX_DWRITESHAPER_H
|
||||
#define GFX_DWRITESHAPER_H
|
||||
|
||||
#include "gfxDWriteFonts.h"
|
||||
|
||||
/**
|
||||
* \brief Class representing a DWrite font shaper.
|
||||
*/
|
||||
class gfxDWriteShaper : public gfxFontShaper
|
||||
{
|
||||
public:
|
||||
gfxDWriteShaper(gfxDWriteFont *aFont)
|
||||
: gfxFontShaper(aFont)
|
||||
{ }
|
||||
|
||||
virtual ~gfxDWriteShaper() { }
|
||||
|
||||
virtual PRBool InitTextRun(gfxContext *aContext,
|
||||
gfxTextRun *aTextRun,
|
||||
const PRUnichar *aString,
|
||||
PRUint32 aRunStart,
|
||||
PRUint32 aRunLength);
|
||||
};
|
||||
|
||||
#endif /* GFX_DWRITESHAPER_H */
|
@ -314,15 +314,7 @@ gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
return new gfxFT2FontGroup(aFamilies, aStyle);
|
||||
#else
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
if (GetDWriteFactory()) {
|
||||
return new gfxDWriteFontGroup(aFamilies, aStyle, aUserFontSet);
|
||||
} else {
|
||||
#endif
|
||||
return new gfxFontGroup(aFamilies, aStyle, aUserFontSet);
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
}
|
||||
#endif
|
||||
return new gfxFontGroup(aFamilies, aStyle, aUserFontSet);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user