Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(767)

Side by Side Diff: Source/platform/fonts/Font.cpp

Issue 676523003: Offset-only GlyphBuffer (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: minor cleanup Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org) 4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved.
6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. 6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved.
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 } 101 }
102 102
103 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph Buffer, 103 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph Buffer,
104 ForTextEmphasisOrNot forTextEmphasis) const 104 ForTextEmphasisOrNot forTextEmphasis) const
105 { 105 {
106 if (codePath(runInfo) == ComplexPath) { 106 if (codePath(runInfo) == ComplexPath) {
107 HarfBuzzShaper shaper(this, runInfo.run, (forTextEmphasis == ForTextEmph asis) 107 HarfBuzzShaper shaper(this, runInfo.run, (forTextEmphasis == ForTextEmph asis)
108 ? HarfBuzzShaper::ForTextEmphasis : HarfBuzzShaper::NotForTextEmphas is); 108 ? HarfBuzzShaper::ForTextEmphasis : HarfBuzzShaper::NotForTextEmphas is);
109 shaper.setDrawRange(runInfo.from, runInfo.to); 109 shaper.setDrawRange(runInfo.from, runInfo.to);
110 shaper.shape(&glyphBuffer); 110 shaper.shape(&glyphBuffer);
111 111 return shaper.totalWidth();
112 return 0;
113 } 112 }
114 113
115 SimpleShaper shaper(this, runInfo.run, nullptr /* fallbackFonts */, 114 SimpleShaper shaper(this, runInfo.run, nullptr /* fallbackFonts */,
116 nullptr /* GlyphBounds */, forTextEmphasis); 115 nullptr /* GlyphBounds */, forTextEmphasis);
117 shaper.advance(runInfo.from); 116 shaper.advance(runInfo.from);
118 float beforeWidth = shaper.runWidthSoFar();
119 shaper.advance(runInfo.to, &glyphBuffer); 117 shaper.advance(runInfo.to, &glyphBuffer);
118 float width = shaper.runWidthSoFar();
120 119
121 if (runInfo.run.ltr()) 120 if (runInfo.run.rtl()) {
jbroman 2014/10/29 15:06:07 Can you add a comment clarifying how this RTL code
f(malita) 2014/10/29 16:48:29 Added a comment + more comprehensive explanation i
122 return beforeWidth; 121 shaper.advance(runInfo.run.length());
122 glyphBuffer.reverse(width, shaper.runWidthSoFar());
123 }
123 124
124 // RTL 125 return width;
125 float afterWidth = shaper.runWidthSoFar();
126 shaper.advance(runInfo.run.length());
127 glyphBuffer.reverse();
128
129 return shaper.runWidthSoFar() - afterWidth;
130 } 126 }
131 127
132 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, 128 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo,
133 const FloatPoint& point) const 129 const FloatPoint& point) const
134 { 130 {
135 // Don't draw anything while we are using custom fonts that are in the proce ss of loading. 131 // Don't draw anything while we are using custom fonts that are in the proce ss of loading.
136 if (shouldSkipDrawing()) 132 if (shouldSkipDrawing())
137 return; 133 return;
138 134
139 TextDrawingModeFlags textMode = context->textDrawingMode(); 135 TextDrawingModeFlags textMode = context->textDrawingMode();
140 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke())) 136 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke()))
141 return; 137 return;
142 138
143 if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) { 139 if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) {
144 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); 140 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
145 // we have a pre-cached blob -- happy joy! 141 // we have a pre-cached blob -- happy joy!
146 drawTextBlob(context, runInfo.cachedTextBlob->get(), point.data()); 142 drawTextBlob(context, runInfo.cachedTextBlob->get(), point.data());
147 return; 143 return;
148 } 144 }
149 145
150 GlyphBuffer glyphBuffer; 146 GlyphBuffer glyphBuffer;
151 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); 147 buildGlyphBuffer(runInfo, glyphBuffer);
152 148
153 if (glyphBuffer.isEmpty()) 149 if (glyphBuffer.isEmpty())
154 return; 150 return;
155 151
156 if (RuntimeEnabledFeatures::textBlobEnabled()) { 152 if (RuntimeEnabledFeatures::textBlobEnabled()) {
157 // Enabling text-blobs forces the blob rendering path even for uncacheab le blobs. 153 // Enabling text-blobs forces the blob rendering path even for uncacheab le blobs.
158 TextBlobPtr uncacheableTextBlob; 154 TextBlobPtr uncacheableTextBlob;
159 TextBlobPtr& textBlob = runInfo.cachedTextBlob ? *runInfo.cachedTextBlob : uncacheableTextBlob; 155 TextBlobPtr& textBlob = runInfo.cachedTextBlob ? *runInfo.cachedTextBlob : uncacheableTextBlob;
160 FloatRect blobBounds = runInfo.bounds; 156 FloatRect blobBounds = runInfo.bounds;
161 blobBounds.moveBy(-point); 157 blobBounds.moveBy(-point);
162 158
163 textBlob = buildTextBlob(glyphBuffer, initialAdvance, blobBounds, contex t->couldUseLCDRenderedText()); 159 textBlob = buildTextBlob(glyphBuffer, blobBounds, context->couldUseLCDRe nderedText());
164 if (textBlob) { 160 if (textBlob) {
165 drawTextBlob(context, textBlob.get(), point.data()); 161 drawTextBlob(context, textBlob.get(), point.data());
166 return; 162 return;
167 } 163 }
168 } 164 }
169 165
170 drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() + initia lAdvance, point.y())); 166 drawGlyphBuffer(context, runInfo, glyphBuffer, point);
171 } 167 }
172 168
173 float Font::drawUncachedText(GraphicsContext* context, const TextRunPaintInfo& r unInfo, 169 float Font::drawUncachedText(GraphicsContext* context, const TextRunPaintInfo& r unInfo,
174 const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const 170 const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const
175 { 171 {
176 // Don't draw anything while we are using custom fonts that are in the proce ss of loading, 172 // Don't draw anything while we are using custom fonts that are in the proce ss of loading,
177 // except if the 'force' argument is set to true (in which case it will use a fallback 173 // except if the 'force' argument is set to true (in which case it will use a fallback
178 // font). 174 // font).
179 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotRe ady) 175 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotRe ady)
180 return 0; 176 return 0;
181 177
182 TextDrawingModeFlags textMode = context->textDrawingMode(); 178 TextDrawingModeFlags textMode = context->textDrawingMode();
183 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke())) 179 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke()))
184 return 0; 180 return 0;
185 181
186 GlyphBuffer glyphBuffer; 182 GlyphBuffer glyphBuffer;
187 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); 183 float totalAdvance = buildGlyphBuffer(runInfo, glyphBuffer);
188 184
189 if (glyphBuffer.isEmpty()) 185 if (glyphBuffer.isEmpty())
190 return 0; 186 return 0;
191 187
192 return drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() + initialAdvance, point.y())); 188 drawGlyphBuffer(context, runInfo, glyphBuffer, point);
189
190 return totalAdvance;
193 } 191 }
194 192
195 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const AtomicString& mark, const FloatPoint& point) const 193 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const AtomicString& mark, const FloatPoint& point) const
196 { 194 {
197 if (shouldSkipDrawing()) 195 if (shouldSkipDrawing())
198 return; 196 return;
199 197
200 GlyphBuffer glyphBuffer; 198 GlyphBuffer glyphBuffer;
201 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer, ForTextEmphasi s); 199 buildGlyphBuffer(runInfo, glyphBuffer, ForTextEmphasis);
202 200
203 if (glyphBuffer.isEmpty()) 201 if (glyphBuffer.isEmpty())
204 return; 202 return;
205 203
206 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); 204 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, point);
207 } 205 }
208 206
209 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound s, 207 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound s,
210 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) 208 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow)
211 { 209 {
212 glyphOverflow->top = std::max<int>(glyphOverflow->top, 210 glyphOverflow->top = std::max<int>(glyphOverflow->top,
213 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce nt())); 211 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce nt()));
214 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, 212 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom,
215 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d escent())); 213 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d escent()));
216 glyphOverflow->left = glyphBounds.left(); 214 glyphOverflow->left = glyphBounds.left();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) { 250 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) {
253 cacheEntry->glyphBounds = glyphBounds; 251 cacheEntry->glyphBounds = glyphBounds;
254 cacheEntry->width = result; 252 cacheEntry->width = result;
255 } 253 }
256 254
257 if (glyphOverflow) 255 if (glyphOverflow)
258 updateGlyphOverflowFromBounds(glyphBounds, fontMetrics(), glyphOverflow) ; 256 updateGlyphOverflowFromBounds(glyphBounds, fontMetrics(), glyphOverflow) ;
259 return result; 257 return result;
260 } 258 }
261 259
262 namespace { 260 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, const FloatR ect& bounds,
261 bool couldUseLCD) const
262 {
263 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
263 264
264 template <bool hasOffsets> 265 SkTextBlobBuilder builder;
265 bool buildTextBlobInternal(const GlyphBuffer& glyphBuffer, SkScalar initialAdvan ce, 266 SkRect skBounds = bounds;
266 const SkRect* bounds, bool couldUseLCD, SkTextBlobBuilder& builder) 267 bool hasVerticalOffsets = glyphBuffer.hasVerticalOffsets();
267 { 268
268 SkScalar x = initialAdvance;
269 unsigned i = 0; 269 unsigned i = 0;
270 while (i < glyphBuffer.size()) { 270 while (i < glyphBuffer.size()) {
271 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i); 271 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i);
272 272
273 // FIXME: Handle vertical text. 273 // FIXME: Handle vertical text.
274 if (fontData->platformData().orientation() == Vertical) 274 if (fontData->platformData().orientation() == Vertical)
275 return false; 275 return nullptr;
276 276
277 // FIXME: FontPlatformData makes some decisions on the device scale 277 // FIXME: FontPlatformData makes some decisions on the device scale
278 // factor, which is found via the GraphicsContext. This should be fixed 278 // factor, which is found via the GraphicsContext. This should be fixed
279 // to avoid correctness problems here. 279 // to avoid correctness problems here.
280 SkPaint paint; 280 SkPaint paint;
281 fontData->platformData().setupPaint(&paint); 281 fontData->platformData().setupPaint(&paint);
282 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 282 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
283 283
284 // FIXME: this should go away after the big LCD cleanup. 284 // FIXME: this should go away after the big LCD cleanup.
285 paint.setLCDRenderText(paint.isLCDRenderText() && couldUseLCD); 285 paint.setLCDRenderText(paint.isLCDRenderText() && couldUseLCD);
286 286
287 unsigned start = i++; 287 unsigned start = i++;
288 while (i < glyphBuffer.size() && glyphBuffer.fontDataAt(i) == fontData) 288 while (i < glyphBuffer.size() && glyphBuffer.fontDataAt(i) == fontData)
289 i++; 289 i++;
290 unsigned count = i - start; 290 unsigned count = i - start;
291 291
292 const SkTextBlobBuilder::RunBuffer& buffer = hasOffsets ? 292 const SkTextBlobBuilder::RunBuffer& buffer = hasVerticalOffsets
293 builder.allocRunPos(paint, count, bounds) : 293 ? builder.allocRunPos(paint, count, &skBounds)
294 builder.allocRunPosH(paint, count, 0, bounds); 294 : builder.allocRunPosH(paint, count, 0, &skBounds);
295 295
296 const uint16_t* glyphs = glyphBuffer.glyphs(start); 296 const uint16_t* glyphs = glyphBuffer.glyphs(start);
297 const float* offsets = glyphBuffer.offsets(start);
297 std::copy(glyphs, glyphs + count, buffer.glyphs); 298 std::copy(glyphs, glyphs + count, buffer.glyphs);
299 std::copy(offsets, offsets + (hasVerticalOffsets ? 2 * count : count), b uffer.pos);
300 }
298 301
299 const float* advances = glyphBuffer.advances(start); 302 return adoptRef(builder.build());
300 const FloatSize* offsets = glyphBuffer.offsets(start);
301 for (unsigned j = 0; j < count; j++) {
302 if (hasOffsets) {
303 const FloatSize& offset = offsets[j];
304 buffer.pos[2 * j] = x + offset.width();
305 buffer.pos[2 * j + 1] = offset.height();
306 } else {
307 buffer.pos[j] = x;
308 }
309 x += SkFloatToScalar(advances[j]);
310 }
311 }
312 return true;
313 }
314
315 } // namespace
316
317 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initia lAdvance,
318 const FloatRect& bounds, bool couldUseLCD) const
319 {
320 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
321
322 SkTextBlobBuilder builder;
323 SkScalar advance = SkFloatToScalar(initialAdvance);
324 SkRect skBounds = bounds;
325
326 bool success = glyphBuffer.hasOffsets() ?
327 buildTextBlobInternal<true>(glyphBuffer, advance, &skBounds, couldUseLCD , builder) :
328 buildTextBlobInternal<false>(glyphBuffer, advance, &skBounds, couldUseLC D, builder);
329 return success ? adoptRef(builder.build()) : nullptr;
330 } 303 }
331 304
332 static inline FloatRect pixelSnappedSelectionRect(FloatRect rect) 305 static inline FloatRect pixelSnappedSelectionRect(FloatRect rect)
333 { 306 {
334 // Using roundf() rather than ceilf() for the right edge as a compromise to 307 // Using roundf() rather than ceilf() for the right edge as a compromise to
335 // ensure correct caret positioning. 308 // ensure correct caret positioning.
336 float roundedX = roundf(rect.x()); 309 float roundedX = roundf(rect.x());
337 return FloatRect(roundedX, rect.y(), roundf(rect.maxX() - roundedX), rect.he ight()); 310 return FloatRect(roundedX, rect.y(), roundf(rect.maxX() - roundedX), rect.he ight());
338 } 311 }
339 312
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 SkPaint paint = textFillPaint(gc, font); 780 SkPaint paint = textFillPaint(gc, font);
808 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint); 781 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint);
809 } 782 }
810 783
811 if ((textMode & TextModeStroke) && gc->hasStroke()) { 784 if ((textMode & TextModeStroke) && gc->hasStroke()) {
812 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill); 785 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill);
813 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint); 786 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint);
814 } 787 }
815 } 788 }
816 789
790 static void drawVerticalGlyphs(GraphicsContext* gc, const SimpleFontData* font,
791 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const Flo atPoint& point,
792 const FloatRect& textRect)
793 {
794 const OpenTypeVerticalData* verticalData = font->verticalData();
795
796 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
797 SkPoint* pos = storage.get();
798
799 // Bend over backwards to preserve legacy rounding.
800 float initialAdvance = glyphBuffer.xOffsetAt(from);
801 FloatPoint adjustedPoint(point.x() + initialAdvance, point.y());
802
803 AffineTransform savedMatrix = gc->getCTM();
804 gc->concatCTM(AffineTransform(0, -1, 1, 0, adjustedPoint.x(), adjustedPoint. y()));
805 gc->concatCTM(AffineTransform(1, 0, 0, 1, -adjustedPoint.x(), -adjustedPoint .y()));
806
807 const unsigned kMaxBufferLength = 256;
808 Vector<FloatPoint, kMaxBufferLength> translations;
809
810 const FontMetrics& metrics = font->fontMetrics();
811 float verticalOriginX = adjustedPoint.x() + metrics.floatAscent() - metrics. floatAscent(IdeographicBaseline);
812
813 unsigned glyphIndex = 0;
814 while (glyphIndex < numGlyphs) {
815 unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphIndex );
816
817 const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
818
819 translations.resize(chunkLength);
820 verticalData->getVerticalTranslationsForGlyphs(font, glyphs, chunkLength ,
821 reinterpret_cast<float*>(&translations[0]));
822
823 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) {
824 SkScalar x = verticalOriginX + lroundf(translations[i].x());
825 SkScalar y = adjustedPoint.y() - SkIntToScalar(
826 -lroundf(glyphBuffer.xOffsetAt(from + glyphIndex) - initialAdvan ce - translations[i].y()));
827 pos[i].set(x, y);
828 }
829 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect);
830 }
831
832 gc->setCTM(savedMatrix);
833 }
834
817 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, 835 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
818 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, 836 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs,
819 const FloatPoint& point, const FloatRect& textRect) const 837 const FloatPoint& point, const FloatRect& textRect) const
820 { 838 {
821 SkScalar x = SkFloatToScalar(point.x()); 839 ASSERT(glyphBuffer.size() >= from + numGlyphs);
822 SkScalar y = SkFloatToScalar(point.y());
823 840
824 const OpenTypeVerticalData* verticalData = font->verticalData(); 841 if (font->platformData().orientation() == Vertical && font->verticalData()) {
825 if (font->platformData().orientation() == Vertical && verticalData) { 842 drawVerticalGlyphs(gc, font, glyphBuffer, from, numGlyphs, point, textRe ct);
826 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
827 SkPoint* pos = storage.get();
828
829 AffineTransform savedMatrix = gc->getCTM();
830 gc->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y()));
831 gc->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y()));
832
833 const unsigned kMaxBufferLength = 256;
834 Vector<FloatPoint, kMaxBufferLength> translations;
835
836 const FontMetrics& metrics = font->fontMetrics();
837 SkScalar verticalOriginX = SkFloatToScalar(point.x() + metrics.floatAsce nt() - metrics.floatAscent(IdeographicBaseline));
838 float horizontalOffset = point.x();
839
840 unsigned glyphIndex = 0;
841 while (glyphIndex < numGlyphs) {
842 unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphI ndex);
843
844 const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
845 translations.resize(chunkLength);
846 verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chu nkLength, reinterpret_cast<float*>(&translations[0]));
847
848 x = verticalOriginX;
849 y = SkFloatToScalar(point.y() + horizontalOffset - point.x());
850
851 float currentWidth = 0;
852 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) {
853 pos[i].set(
854 x + SkIntToScalar(lroundf(translations[i].x())),
855 y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y ())));
856 currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
857 }
858 horizontalOffset += currentWidth;
859 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect);
860 }
861
862 gc->setCTM(savedMatrix);
863 return; 843 return;
864 } 844 }
865 845
866 if (!glyphBuffer.hasOffsets()) { 846 if (!glyphBuffer.hasVerticalOffsets()) {
867 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); 847 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs);
868 SkScalar* xpos = storage.get(); 848 SkScalar* xpos = storage.get();
869 const float* adv = glyphBuffer.advances(from); 849 for (unsigned i = 0; i < numGlyphs; i++)
870 for (unsigned i = 0; i < numGlyphs; i++) { 850 xpos[i] = SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i ));
871 xpos[i] = x; 851
872 x += SkFloatToScalar(adv[i]); 852 paintGlyphsHorizontal(gc, font, glyphBuffer.glyphs(from), numGlyphs, xpo s,
873 } 853 SkFloatToScalar(point.y()), textRect);
874 const Glyph* glyphs = glyphBuffer.glyphs(from);
875 paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar (y), textRect);
876 return; 854 return;
877 } 855 }
878 856
879 ASSERT(glyphBuffer.hasOffsets()); 857 ASSERT(glyphBuffer.hasVerticalOffsets());
880 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); 858 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
881 SkPoint* pos = storage.get(); 859 SkPoint* pos = storage.get();
882 const FloatSize* offsets = glyphBuffer.offsets(from);
883 const float* advances = glyphBuffer.advances(from);
884 SkScalar advanceSoFar = SkFloatToScalar(0);
885 for (unsigned i = 0; i < numGlyphs; i++) { 860 for (unsigned i = 0; i < numGlyphs; i++) {
886 pos[i].set( 861 pos[i].set(
887 x + SkFloatToScalar(offsets[i].width()) + advanceSoFar, 862 SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i)),
888 y + SkFloatToScalar(offsets[i].height())); 863 SkFloatToScalar(point.y() + glyphBuffer.yOffsetAt(from + i)));
889 advanceSoFar += SkFloatToScalar(advances[i]);
890 } 864 }
891 865
892 const Glyph* glyphs = glyphBuffer.glyphs(from); 866 paintGlyphs(gc, font, glyphBuffer.glyphs(from), numGlyphs, pos, textRect);
893 paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect);
894 } 867 }
895 868
896 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi nt& origin) const 869 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi nt& origin) const
897 { 870 {
898 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); 871 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
899 872
900 TextDrawingModeFlags textMode = gc->textDrawingMode(); 873 TextDrawingModeFlags textMode = gc->textDrawingMode();
901 if (textMode & TextModeFill) 874 if (textMode & TextModeFill)
902 gc->drawTextBlob(blob, origin, gc->fillPaint()); 875 gc->drawTextBlob(blob, origin, gc->fillPaint());
903 876
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 // Return the rectangle for selecting the given range of code-points in the Text Run. 909 // Return the rectangle for selecting the given range of code-points in the Text Run.
937 FloatRect Font::selectionRectForComplexText(const TextRun& run, 910 FloatRect Font::selectionRectForComplexText(const TextRun& run,
938 const FloatPoint& point, int height, int from, int to) const 911 const FloatPoint& point, int height, int from, int to) const
939 { 912 {
940 HarfBuzzShaper shaper(this, run); 913 HarfBuzzShaper shaper(this, run);
941 if (!shaper.shape()) 914 if (!shaper.shape())
942 return FloatRect(); 915 return FloatRect();
943 return shaper.selectionRect(point, height, from, to); 916 return shaper.selectionRect(point, height, from, to);
944 } 917 }
945 918
946 float Font::drawGlyphBuffer(GraphicsContext* context, 919 void Font::drawGlyphBuffer(GraphicsContext* context,
947 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, 920 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer,
948 const FloatPoint& point) const 921 const FloatPoint& point) const
949 { 922 {
950 // Draw each contiguous run of glyphs that use the same font data. 923 // Draw each contiguous run of glyphs that use the same font data.
951 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); 924 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
952 FloatPoint startPoint(point);
953 float advanceSoFar = 0;
954 unsigned lastFrom = 0; 925 unsigned lastFrom = 0;
955 unsigned nextGlyph = 0; 926 unsigned nextGlyph;
956 927
957 while (nextGlyph < glyphBuffer.size()) { 928 for (nextGlyph = 0; nextGlyph < glyphBuffer.size(); ++nextGlyph) {
958 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); 929 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
959 930
960 if (nextFontData != fontData) { 931 if (nextFontData != fontData) {
961 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las tFrom, startPoint, runInfo.bounds); 932 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las tFrom, point,
933 runInfo.bounds);
962 934
963 lastFrom = nextGlyph; 935 lastFrom = nextGlyph;
964 fontData = nextFontData; 936 fontData = nextFontData;
965 startPoint += FloatSize(advanceSoFar, 0);
966 advanceSoFar = 0;
967 } 937 }
968 advanceSoFar += glyphBuffer.advanceAt(nextGlyph);
969 nextGlyph++;
970 } 938 }
971 939
972 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, s tartPoint, runInfo.bounds); 940 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p oint,
973 startPoint += FloatSize(advanceSoFar, 0); 941 runInfo.bounds);
974 return startPoint.x() - point.x();
975 } 942 }
976 943
977 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) 944 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
978 { 945 {
979 if (fontData->platformData().orientation() == Horizontal) { 946 if (fontData->platformData().orientation() == Horizontal) {
980 FloatRect bounds = fontData->boundsForGlyph(glyph); 947 FloatRect bounds = fontData->boundsForGlyph(glyph);
981 return bounds.x() + bounds.width() / 2; 948 return bounds.x() + bounds.width() / 2;
982 } 949 }
983 // FIXME: Use glyph bounds once they make sense for vertical fonts. 950 // FIXME: Use glyph bounds once they make sense for vertical fonts.
984 return fontData->widthForGlyph(glyph) / 2; 951 return fontData->widthForGlyph(glyph) / 2;
985 } 952 }
986 953
987 inline static float offsetToMiddleOfAdvanceAtIndex(const GlyphBuffer& glyphBuffe r, size_t i)
988 {
989 return glyphBuffer.advanceAt(i) / 2;
990 }
991
992 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi nt& point) const 954 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi nt& point) const
993 { 955 {
994 FontCachePurgePreventer purgePreventer; 956 FontCachePurgePreventer purgePreventer;
995 957
996 GlyphData markGlyphData; 958 GlyphData markGlyphData;
997 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 959 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
998 return; 960 return;
999 961
1000 const SimpleFontData* markFontData = markGlyphData.fontData; 962 const SimpleFontData* markFontData = markGlyphData.fontData;
1001 ASSERT(markFontData); 963 ASSERT(markFontData);
1002 if (!markFontData) 964 if (!markFontData)
1003 return; 965 return;
1004 966
1005 Glyph markGlyph = markGlyphData.glyph; 967 GlyphBuffer markBuffer;
1006 Glyph spaceGlyph = markFontData->spaceGlyph(); 968 float midMarkOffset = offsetToMiddleOfGlyph(markFontData, markGlyphData.glyp h);
jbroman 2014/10/29 15:06:07 Can you clarify why we're subtracting midMarkOffse
f(malita) 2014/10/29 16:48:29 Added some comments (we are essentially aligning t
969 for (unsigned i = 0; i < glyphBuffer.size(); ++i) {
970 // Offsets point to glyphs midpoint.
971 if (glyphBuffer.glyphAt(i))
972 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffse tAt(i) - midMarkOffset);
973 }
1007 974
1008 float middleOfLastGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, 0); 975 drawGlyphBuffer(context, runInfo, markBuffer, point);
1009 FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph( markFontData, markGlyph), point.y());
1010
1011 GlyphBuffer markBuffer;
1012 for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) {
1013 float middleOfNextGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, i + 1);
1014 float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfN extGlyph;
1015 markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFont Data, advance);
1016 middleOfLastGlyph = middleOfNextGlyph;
1017 }
1018 markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spa ceGlyph, markFontData, 0);
1019
1020 drawGlyphBuffer(context, runInfo, markBuffer, startPoint);
1021 } 976 }
1022 977
1023 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont Data*>* fallbackFonts, IntRectExtent* glyphBounds) const 978 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont Data*>* fallbackFonts, IntRectExtent* glyphBounds) const
1024 { 979 {
1025 SimpleShaper::GlyphBounds bounds; 980 SimpleShaper::GlyphBounds bounds;
1026 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); 981 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0);
1027 shaper.advance(run.length()); 982 shaper.advance(run.length());
1028 983
1029 if (glyphBounds) { 984 if (glyphBounds) {
1030 glyphBounds->setTop(floorf(-bounds.minGlyphBoundingBoxY)); 985 glyphBounds->setTop(floorf(-bounds.minGlyphBoundingBoxY));
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 if (delta <= 0) 1051 if (delta <= 0)
1097 break; 1052 break;
1098 } 1053 }
1099 } 1054 }
1100 } 1055 }
1101 1056
1102 return offset; 1057 return offset;
1103 } 1058 }
1104 1059
1105 } // namespace blink 1060 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698