diff options
author | Iain Merrick <husky@google.com> | 2010-08-19 17:55:56 +0100 |
---|---|---|
committer | Iain Merrick <husky@google.com> | 2010-08-23 11:05:40 +0100 |
commit | f486d19d62f1bc33246748b14b14a9dfa617b57f (patch) | |
tree | 195485454c93125455a30e553a73981c3816144d /WebCore/platform/graphics/chromium | |
parent | 6ba0b43722d16bc295606bec39f396f596e4fef1 (diff) | |
download | external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.zip external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.tar.gz external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.tar.bz2 |
Merge WebKit at r65615 : Initial merge by git.
Change-Id: Ifbf384f4531e3b58475a662e38195c2d9152ae79
Diffstat (limited to 'WebCore/platform/graphics/chromium')
17 files changed, 573 insertions, 77 deletions
diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp index 8ba37c6..7c3e450 100644 --- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp @@ -38,8 +38,8 @@ #include "HashMap.h" #include "HashSet.h" #include "SimpleFontData.h" -#include "StringHash.h" #include <unicode/uniset.h> +#include <wtf/text/StringHash.h> #include <windows.h> #include <objidl.h> diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp index 53f4a52..2fda22d 100644 --- a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "FontCache.h" -#include "AtomicString.h" #include "ChromiumBridge.h" #include "Font.h" #include "FontDescription.h" @@ -46,6 +45,7 @@ #include <unicode/utf16.h> #include <wtf/Assertions.h> +#include <wtf/text/AtomicString.h> #include <wtf/text/CString.h> namespace WebCore { diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp index 1953dd8..ec79b82 100644 --- a/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -166,6 +166,9 @@ public: , m_offsetX(m_startingX) , m_run(getTextRun(run)) , m_iterateBackwards(m_run.rtl()) + , m_wordSpacingAdjustment(0) + , m_padding(0) + , m_padError(0) { // Do not use |run| inside this constructor. Use |m_run| instead. @@ -207,6 +210,56 @@ public: delete[] m_item.string; } + // setWordSpacingAdjustment sets a delta (in pixels) which is applied at + // each word break in the TextRun. + void setWordSpacingAdjustment(int wordSpacingAdjustment) + { + m_wordSpacingAdjustment = wordSpacingAdjustment; + } + + // setLetterSpacingAdjustment sets an additional number of pixels that is + // added to the advance after each output cluster. This matches the behaviour + // of WidthIterator::advance. + // + // (NOTE: currently does nothing because I don't know how to get the + // cluster information from Harfbuzz.) + void setLetterSpacingAdjustment(int letterSpacingAdjustment) + { + m_letterSpacing = letterSpacingAdjustment; + } + + bool isWordBreak(unsigned i, bool isRTL) + { + if (!isRTL) + return i && isCodepointSpace(m_item.string[i]) && !isCodepointSpace(m_item.string[i - 1]); + return i != m_item.stringLength - 1 && isCodepointSpace(m_item.string[i]) && !isCodepointSpace(m_item.string[i + 1]); + } + + // setPadding sets a number of pixels to be distributed across the TextRun. + // WebKit uses this to justify text. + void setPadding(int padding) + { + m_padding = padding; + if (!m_padding) + return; + + // If we have padding to distribute, then we try to give an equal + // amount to each space. The last space gets the smaller amount, if + // any. + unsigned numWordBreaks = 0; + bool isRTL = m_iterateBackwards; + + for (unsigned i = 0; i < m_item.stringLength; i++) { + if (isWordBreak(i, isRTL)) + numWordBreaks++; + } + + if (numWordBreaks) + m_padPerWordBreak = m_padding / numWordBreaks; + else + m_padPerWordBreak = 0; + } + void reset() { if (m_iterateBackwards) @@ -453,8 +506,15 @@ private: void setGlyphXPositions(bool isRTL) { double position = 0; + // logClustersIndex indexes logClusters for the first (or last when + // RTL) codepoint of the current glyph. Each time we advance a glyph, + // we skip over all the codepoints that contributed to the current + // glyph. + unsigned logClustersIndex = isRTL ? m_item.num_glyphs - 1 : 0; + for (int iter = 0; iter < m_item.num_glyphs; ++iter) { - // Glyphs are stored in logical order, but for layout purposes we always go left to right. + // Glyphs are stored in logical order, but for layout purposes we + // always go left to right. int i = isRTL ? m_item.num_glyphs - iter - 1 : iter; m_glyphs16[i] = m_item.glyphs[i]; @@ -462,12 +522,48 @@ private: m_xPositions[i] = m_offsetX + position + offsetX; double advance = truncateFixedPointToInteger(m_item.advances[i]); + unsigned glyphIndex = m_item.item.pos + logClustersIndex; + if (isWordBreak(glyphIndex, isRTL)) { + advance += m_wordSpacingAdjustment; + + if (m_padding > 0) { + unsigned toPad = roundf(m_padPerWordBreak + m_padError); + m_padError += m_padPerWordBreak - toPad; + + if (m_padding < toPad) + toPad = m_padding; + m_padding -= toPad; + advance += toPad; + } + } + + // We would like to add m_letterSpacing after each cluster, but I + // don't know where the cluster information is. This is typically + // fine for Roman languages, but breaks more complex languages + // terribly. + // advance += m_letterSpacing; + + if (isRTL) { + while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i) + logClustersIndex--; + } else { + while (logClustersIndex < m_item.num_glyphs && logClusters()[logClustersIndex] == i) + logClustersIndex++; + } + position += advance; } + m_pixelWidth = position; m_offsetX += m_pixelWidth; } + static bool isCodepointSpace(HB_UChar16 c) + { + // This matches the logic in RenderBlock::findNextLineBreak + return c == ' ' || c == '\t'; + } + void mirrorCharacters(UChar* destination, const UChar* source, int length) const { int position = 0; @@ -498,6 +594,14 @@ private: OwnArrayPtr<UChar> m_normalizedBuffer; // A buffer for normalized run. const TextRun& m_run; bool m_iterateBackwards; + int m_wordSpacingAdjustment; // delta adjustment (pixels) for each word break. + float m_padding; // pixels to be distributed over the line at word breaks. + float m_padPerWordBreak; // pixels to be added to each word break. + float m_padError; // |m_padPerWordBreak| might have a fractional component. + // Since we only add a whole number of padding pixels at + // each word break we accumulate error. This is the + // number of pixels that we are behind so far. + unsigned m_letterSpacing; // pixels to be added after each glyph. }; static void setupForTextPainting(SkPaint* paint, SkColor color) @@ -534,6 +638,9 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run, TextRunWalker walker(run, point.x(), this); bool haveMultipleLayers = isCanvasMultiLayered(canvas); + walker.setWordSpacingAdjustment(wordSpacing()); + walker.setLetterSpacingAdjustment(letterSpacing()); + walker.setPadding(run.padding()); while (walker.nextScriptRun()) { if (fill) { @@ -553,6 +660,8 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run, float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const { TextRunWalker walker(run, 0, this); + walker.setWordSpacingAdjustment(wordSpacing()); + walker.setLetterSpacingAdjustment(letterSpacing()); return walker.widthOfFullRun(); } @@ -588,6 +697,8 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, // (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, this); + walker.setWordSpacingAdjustment(wordSpacing()); + walker.setLetterSpacingAdjustment(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 @@ -664,6 +775,8 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, { int fromX = -1, toX = -1, fromAdvance = -1, toAdvance = -1; TextRunWalker walker(run, 0, this); + walker.setWordSpacingAdjustment(wordSpacing()); + walker.setLetterSpacingAdjustment(letterSpacing()); // Base will point to the x offset for the current script run. Note that, in // the LTR case, width will be 0. diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h index 1d6cc8e..beac0bf 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h +++ b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h @@ -34,10 +34,10 @@ #include "config.h" -#include "StringImpl.h" #include <wtf/Forward.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> +#include <wtf/text/StringImpl.h> #include <usp10.h> diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index 9b54732..b51eb8c 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -35,11 +35,12 @@ #include "HarfbuzzSkia.h" #include "NotImplemented.h" #include "PlatformString.h" -#include "StringImpl.h" #include "SkPaint.h" #include "SkTypeface.h" +#include <wtf/text/StringImpl.h> + namespace WebCore { static SkPaint::Hinting skiaHinting = SkPaint::kNormal_Hinting; diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h index de12832..363e55f 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h @@ -32,10 +32,10 @@ #define FontPlatformDataLinux_h #include "FontRenderStyle.h" -#include "StringImpl.h" #include <wtf/Forward.h> #include <wtf/RefPtr.h> #include <wtf/text/CString.h> +#include <wtf/text/StringImpl.h> #include <SkPaint.h> class SkTypeface; diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp index 78170a9..e725c50 100644 --- a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp @@ -34,11 +34,11 @@ #include <limits> #include "PlatformString.h" -#include "StringHash.h" #include "UniscribeHelper.h" #include <unicode/locid.h> #include <unicode/uchar.h> #include <wtf/HashMap.h> +#include <wtf/text/StringHash.h> namespace WebCore { diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp index 8a9bde1..534de7b 100644 --- a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp +++ b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp @@ -38,14 +38,15 @@ #include "FloatRect.h" #include "GLES2Texture.h" #include "GraphicsContext3D.h" +#include "IntRect.h" #include "PlatformString.h" #include "Uint16Array.h" #define _USE_MATH_DEFINES #include <math.h> -#include <wtf/text/CString.h> #include <wtf/OwnArrayPtr.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -221,7 +222,6 @@ void GLES2Canvas::drawTexturedRect(GLES2Texture* texture, const FloatRect& srcRe checkGLError("glUseProgram"); m_context->activeTexture(GraphicsContext3D::TEXTURE0); - texture->bind(); m_context->uniform1i(m_texSamplerLocation, 0); checkGLError("glUniform1i"); @@ -229,28 +229,52 @@ void GLES2Canvas::drawTexturedRect(GLES2Texture* texture, const FloatRect& srcRe m_context->uniform1f(m_texAlphaLocation, alpha); checkGLError("glUniform1f for alpha"); + m_context->vertexAttribPointer(m_texPositionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); + + m_context->enableVertexAttribArray(m_texPositionLocation); + + const TilingData& tiles = texture->tiles(); + IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect); + + for (int y = tileIdxRect.y(); y <= tileIdxRect.bottom(); y++) { + for (int x = tileIdxRect.x(); x <= tileIdxRect.right(); x++) + drawTexturedRectTile(texture, tiles.tileIndex(x, y), srcRect, dstRect, transform); + } +} + +void GLES2Canvas::drawTexturedRectTile(GLES2Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform) +{ + if (dstRect.isEmpty()) + return; + + const TilingData& tiles = texture->tiles(); + + texture->bindTile(tile); + + FloatRect srcRectClippedInTileSpace; + FloatRect dstRectIntersected; + tiles.intersectDrawQuad(srcRect, dstRect, tile, &srcRectClippedInTileSpace, &dstRectIntersected); + + IntRect tileBoundsWithBorder = tiles.tileBoundsWithBorder(tile); + AffineTransform matrix(m_flipMatrix); matrix.multLeft(transform); - matrix.translate(dstRect.x(), dstRect.y()); - matrix.scale(dstRect.width(), dstRect.height()); + matrix.translate(dstRectIntersected.x(), dstRectIntersected.y()); + matrix.scale(dstRectIntersected.width(), dstRectIntersected.height()); float mat[9]; affineTo3x3(matrix, mat); m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, mat, 1 /*count*/); checkGLError("glUniformMatrix3fv"); AffineTransform texMatrix; - texMatrix.scale(1.0f / texture->width(), 1.0f / texture->height()); - texMatrix.translate(srcRect.x(), srcRect.y()); - texMatrix.scale(srcRect.width(), srcRect.height()); + texMatrix.scale(1.0f / tileBoundsWithBorder.width(), 1.0f / tileBoundsWithBorder.height()); + texMatrix.translate(srcRectClippedInTileSpace.x(), srcRectClippedInTileSpace.y()); + texMatrix.scale(srcRectClippedInTileSpace.width(), srcRectClippedInTileSpace.height()); float texMat[9]; affineTo3x3(texMatrix, texMat); m_context->uniformMatrix3fv(m_texTexMatrixLocation, false /*transpose*/, texMat, 1 /*count*/); checkGLError("glUniformMatrix3fv"); - m_context->vertexAttribPointer(m_texPositionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); - - m_context->enableVertexAttribArray(m_texPositionLocation); - m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0); checkGLError("glDrawElements"); } diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.h b/WebCore/platform/graphics/chromium/GLES2Canvas.h index cea90ae..0ad07fc 100644 --- a/WebCore/platform/graphics/chromium/GLES2Canvas.h +++ b/WebCore/platform/graphics/chromium/GLES2Canvas.h @@ -81,6 +81,7 @@ public: GLES2Texture* getTexture(NativeImagePtr); private: + void drawTexturedRectTile(GLES2Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&); void applyCompositeOperator(CompositeOperator); void checkGLError(const char* header); unsigned getQuadVertices(); diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.cpp b/WebCore/platform/graphics/chromium/GLES2Texture.cpp index 5e8a141..ae230db 100644 --- a/WebCore/platform/graphics/chromium/GLES2Texture.cpp +++ b/WebCore/platform/graphics/chromium/GLES2Texture.cpp @@ -35,45 +35,27 @@ #include "GLES2Texture.h" #include "GraphicsContext3D.h" - +#include "IntRect.h" #include <wtf/OwnArrayPtr.h> namespace WebCore { -GLES2Texture::GLES2Texture(GraphicsContext3D* context, unsigned textureId, Format format, int width, int height) + +GLES2Texture::GLES2Texture(GraphicsContext3D* context, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize) : m_context(context) - , m_textureId(textureId) , m_format(format) - , m_width(width) - , m_height(height) + , m_tiles(maxTextureSize, width, height, true) + , m_tileTextureIds(tileTextureIds) { } GLES2Texture::~GLES2Texture() { - m_context->deleteTexture(m_textureId); -} - -PassRefPtr<GLES2Texture> GLES2Texture::create(GraphicsContext3D* context, Format format, int width, int height) -{ - int max; - context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &max); - if (width > max || height > max) { - ASSERT(!"texture too big"); - return 0; - } - - unsigned textureId = context->createTexture(); - if (!textureId) - return 0; - - context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); - context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, width, height, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0); - - return adoptRef(new GLES2Texture(context, textureId, format, width, height)); + for (unsigned int i = 0; i < m_tileTextureIds->size(); i++) + m_context->deleteTexture(m_tileTextureIds->at(i)); } -static void convertFormat(GLES2Texture::Format format, unsigned int* glFormat, unsigned int* glType, bool* swizzle) +static void convertFormat(GraphicsContext3D* context, GLES2Texture::Format format, unsigned int* glFormat, unsigned int* glType, bool* swizzle) { *swizzle = false; switch (format) { @@ -82,43 +64,113 @@ static void convertFormat(GLES2Texture::Format format, unsigned int* glFormat, u *glType = GraphicsContext3D::UNSIGNED_BYTE; break; case GLES2Texture::BGRA8: -// FIXME: Once we have support for extensions, we should check for EXT_texture_format_BGRA8888, -// and use that if present. - *glFormat = GraphicsContext3D::RGBA; - *glType = GraphicsContext3D::UNSIGNED_BYTE; - *swizzle = true; + if (context->supportsBGRA()) { + *glFormat = GraphicsContext3D::BGRA_EXT; + *glType = GraphicsContext3D::UNSIGNED_BYTE; + } else { + *glFormat = GraphicsContext3D::RGBA; + *glType = GraphicsContext3D::UNSIGNED_BYTE; + *swizzle = true; + } break; default: - ASSERT(!"bad format"); + ASSERT_NOT_REACHED(); break; } } +PassRefPtr<GLES2Texture> GLES2Texture::create(GraphicsContext3D* context, Format format, int width, int height) +{ + int maxTextureSize = 0; + context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize); + + TilingData tiling(maxTextureSize, width, height, true); + int numTiles = tiling.numTiles(); + + OwnPtr<Vector<unsigned int> > textureIds(new Vector<unsigned int>(numTiles)); + textureIds->fill(0, numTiles); + + for (int i = 0; i < numTiles; i++) { + int textureId = context->createTexture(); + if (!textureId) { + for (int i = 0; i < numTiles; i++) + context->deleteTexture(textureIds->at(i)); + return 0; + } + textureIds->at(i) = textureId; + + IntRect tileBoundsWithBorder = tiling.tileBoundsWithBorder(i); + + unsigned int glFormat, glType; + bool swizzle; + convertFormat(context, format, &glFormat, &glType, &swizzle); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); + context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, glFormat, + tileBoundsWithBorder.width(), + tileBoundsWithBorder.height(), + 0, glFormat, glType, 0); + } + return adoptRef(new GLES2Texture(context, textureIds.leakPtr(), format, width, height, maxTextureSize)); +} + +template <bool swizzle> +static uint32_t* copySubRect(uint32_t* src, int srcX, int srcY, uint32_t* dst, int width, int height, int srcStride) +{ + uint32_t* srcOffset = src + srcX + srcY * srcStride; + + if (!swizzle && width == srcStride) + return srcOffset; + + uint32_t* dstPixel = dst; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width ; x++) { + uint32_t pixel = srcOffset[x + y * srcStride]; + if (swizzle) + *dstPixel = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16); + else + *dstPixel = pixel; + dstPixel++; + } + } + return dst; +} + void GLES2Texture::load(void* pixels) { + uint32_t* pixels32 = static_cast<uint32_t*>(pixels); unsigned int glFormat, glType; bool swizzle; - convertFormat(m_format, &glFormat, &glType, &swizzle); - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId); + convertFormat(m_context, m_format, &glFormat, &glType, &swizzle); if (swizzle) { ASSERT(glFormat == GraphicsContext3D::RGBA && glType == GraphicsContext3D::UNSIGNED_BYTE); // FIXME: This could use PBO's to save doing an extra copy here. - int size = m_width * m_height; - unsigned* pixels32 = static_cast<unsigned*>(pixels); - OwnArrayPtr<unsigned> buf(new unsigned[size]); - unsigned* bufptr = buf.get(); - for (int i = 0; i < size; ++i) { - unsigned pixel = pixels32[i]; - bufptr[i] = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16); + } + OwnArrayPtr<uint32_t> tempBuff(new uint32_t[m_tiles.maxTextureSize() * m_tiles.maxTextureSize()]); + + for (int i = 0; i < m_tiles.numTiles(); i++) { + IntRect tileBoundsWithBorder = m_tiles.tileBoundsWithBorder(i); + + uint32_t* uploadBuff = 0; + if (swizzle) { + uploadBuff = copySubRect<true>( + pixels32, tileBoundsWithBorder.x(), tileBoundsWithBorder.y(), + tempBuff.get(), tileBoundsWithBorder.width(), tileBoundsWithBorder.height(), m_tiles.totalSizeX()); + } else { + uploadBuff = copySubRect<false>( + pixels32, tileBoundsWithBorder.x(), tileBoundsWithBorder.y(), + tempBuff.get(), tileBoundsWithBorder.width(), tileBoundsWithBorder.height(), m_tiles.totalSizeX()); } - m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, m_width, m_height, glFormat, glType, buf.get()); - } else - m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, m_width, m_height, glFormat, glType, pixels); + + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_tileTextureIds->at(i)); + m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, + tileBoundsWithBorder.width(), + tileBoundsWithBorder.height(), glFormat, glType, uploadBuff); + } } -void GLES2Texture::bind() +void GLES2Texture::bindTile(int tile) { - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_tileTextureIds->at(tile)); m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.h b/WebCore/platform/graphics/chromium/GLES2Texture.h index 4d351cd..43a4955 100644 --- a/WebCore/platform/graphics/chromium/GLES2Texture.h +++ b/WebCore/platform/graphics/chromium/GLES2Texture.h @@ -35,6 +35,10 @@ #include "RefCounted.h" #include "RefPtr.h" +#include "TilingData.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/Vector.h> namespace WebCore { class GraphicsContext3D; @@ -44,18 +48,16 @@ public: ~GLES2Texture(); enum Format { RGBA8, BGRA8 }; static PassRefPtr<GLES2Texture> create(GraphicsContext3D*, Format, int width, int height); - void bind(); + void bindTile(int tile); void load(void* pixels); Format format() const { return m_format; } - int width() const { return m_width; } - int height() const { return m_height; } + const TilingData& tiles() const { return m_tiles; } private: - GLES2Texture(GraphicsContext3D*, unsigned textureId, Format, int width, int height); + GLES2Texture(GraphicsContext3D*, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize); GraphicsContext3D* m_context; - unsigned m_textureId; Format m_format; - int m_width; - int m_height; + TilingData m_tiles; + OwnPtr<Vector<unsigned int> > m_tileTextureIds; }; } diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp index 9f6ee17..3cc7cad 100644 --- a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -114,7 +114,7 @@ void ImageLayerChromium::updateTextureContents(unsigned textureId) case kCGColorSpaceModelDeviceN: break; default: - colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear)); + colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB()); break; } RetainPtr<CGContextRef> tempContext(AdoptCF, CGBitmapContextCreate(tempVector.data(), diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index bba65f4..21d8d12 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -180,8 +180,7 @@ void LayerChromium::updateTextureContents(unsigned textureId) int rowBytes = 4 * dirtyRect.width(); tempVector.resize(rowBytes * dirtyRect.height()); memset(tempVector.data(), 0, tempVector.size()); - // FIXME: unsure whether this is the best color space choice. - RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear)); + RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(), dirtyRect.width(), dirtyRect.height(), 8, rowBytes, colorSpace.get(), diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index ebb4504..9fba415 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -38,12 +38,12 @@ #include "GraphicsContext.h" #include "GraphicsLayerChromium.h" #include "PlatformString.h" -#include "StringHash.h" #include "TransformationMatrix.h" #include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> +#include <wtf/text/StringHash.h> namespace skia { diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index 15acfa5..2f70efa 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -255,8 +255,7 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size) int rowBytes = 4 * size.width(); m_rootLayerBackingStore.resize(rowBytes * size.height()); memset(m_rootLayerBackingStore.data(), 0, m_rootLayerBackingStore.size()); - // FIXME: unsure whether this is the best color space choice. - RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear)); + RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); m_rootLayerCGContext.adoptCF(CGBitmapContextCreate(m_rootLayerBackingStore.data(), size.width(), size.height(), 8, rowBytes, colorSpace.get(), diff --git a/WebCore/platform/graphics/chromium/TilingData.cpp b/WebCore/platform/graphics/chromium/TilingData.cpp new file mode 100755 index 0000000..c52288d --- /dev/null +++ b/WebCore/platform/graphics/chromium/TilingData.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "TilingData.h" + +#include "FloatRect.h" +#include "IntRect.h" +#include <algorithm> + +using namespace std; + +namespace WebCore { + +static int computeNumTiles(int maxTextureSize, int totalSize, int borderTexels) +{ + return max(1, 1 + (totalSize - 1 - 2 * borderTexels) / (maxTextureSize - 2 * borderTexels)); +} + +TilingData::TilingData(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels) + : m_maxTextureSize(maxTextureSize) + , m_totalSizeX(totalSizeX) + , m_totalSizeY(totalSizeY) + , m_borderTexels(hasBorderTexels ? 1 : 0) +{ + m_numTilesX = computeNumTiles(maxTextureSize, m_totalSizeX, m_borderTexels); + m_numTilesY = computeNumTiles(maxTextureSize, m_totalSizeY, m_borderTexels); +} + +int TilingData::tileXIndexFromSrcCoord(int srcPos) const +{ + int x = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels); + return min(max(x, 0), numTilesX() - 1); +} + +int TilingData::tileYIndexFromSrcCoord(int srcPos) const +{ + int y = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels); + return min(max(y, 0), numTilesY() - 1); +} + +IntRect TilingData::tileBounds(int tile) const +{ + assertTile(tile); + int ix = tileXIndex(tile); + int iy = tileYIndex(tile); + int x = tilePositionX(ix); + int y = tilePositionY(iy); + int width = tileSizeX(ix); + int height = tileSizeY(iy); + ASSERT(x >= 0 && y >= 0 && width >= 0 && height >= 0); + ASSERT(x <= totalSizeX() && y <= totalSizeY()); + return IntRect(x, y, width, height); +} + +IntRect TilingData::tileBoundsWithBorder(int tile) const +{ + IntRect bounds = tileBounds(tile); + + if (m_borderTexels) { + int x1 = bounds.x(); + int x2 = bounds.right(); + int y1 = bounds.y(); + int y2 = bounds.bottom(); + + if (tileXIndex(tile) > 0) + x1--; + if (tileXIndex(tile) < (numTilesX() - 1)) + x2++; + if (tileYIndex(tile) > 0) + y1--; + if (tileYIndex(tile) < (numTilesY() - 1)) + y2++; + + bounds = IntRect(x1, y1, x2 - x1, y2 - y1); + } + + return bounds; +} + +FloatRect TilingData::tileBoundsNormalized(int tile) const +{ + assertTile(tile); + FloatRect bounds(tileBounds(tile)); + bounds.scale(1.0f / m_totalSizeX, 1.0f / m_totalSizeY); + return bounds; +} + +int TilingData::tilePositionX(int xIndex) const +{ + ASSERT(xIndex >= 0 && xIndex < numTilesX()); + + if (!xIndex) + return 0; + return tilePositionX(xIndex - 1) + tileSizeX(xIndex - 1); +} + +int TilingData::tilePositionY(int yIndex) const +{ + ASSERT(yIndex >= 0 && yIndex < numTilesY()); + + if (!yIndex) + return 0; + return tilePositionX(yIndex - 1) + tileSizeY(yIndex - 1); +} + +int TilingData::tileSizeX(int xIndex) const +{ + ASSERT(xIndex >= 0 && xIndex < numTilesX()); + + int size = maxTextureSize(); + size = min(size, totalSizeX()); + + if (!xIndex && m_numTilesX == 1) + return m_totalSizeX; + if (!xIndex && m_numTilesX > 1) + return m_maxTextureSize - m_borderTexels; + if (xIndex < numTilesX() - 1) + return m_maxTextureSize - 2 * m_borderTexels; + if (xIndex == numTilesX() - 1) + return m_totalSizeX - tilePositionX(xIndex); + + ASSERT_NOT_REACHED(); + return 0; +} + +int TilingData::tileSizeY(int yIndex) const +{ + ASSERT(yIndex >= 0 && yIndex < numTilesY()); + + int size = maxTextureSize(); + size = min(size, totalSizeY()); + + if (!yIndex && m_numTilesY == 1) + return m_totalSizeY; + if (!yIndex && m_numTilesY > 1) + return m_maxTextureSize - m_borderTexels; + if (yIndex < numTilesY() - 1) + return m_maxTextureSize - 2 * m_borderTexels; + if (yIndex == numTilesY() - 1) + return m_totalSizeY - tilePositionY(yIndex); + + ASSERT_NOT_REACHED(); + return 0; +} + +IntRect TilingData::overlappedTileIndices(const WebCore::IntRect &srcRect) const +{ + int x = tileXIndexFromSrcCoord(srcRect.x()); + int y = tileYIndexFromSrcCoord(srcRect.y()); + int r = tileXIndexFromSrcCoord(srcRect.right()); + int b = tileYIndexFromSrcCoord(srcRect.bottom()); + return IntRect(x, y, r - x, b - y); +} + +IntRect TilingData::overlappedTileIndices(const WebCore::FloatRect &srcRect) const +{ + return overlappedTileIndices(enclosingIntRect(srcRect)); +} + +void TilingData::intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile, + FloatRect* newSrc, FloatRect* newDst) const +{ + // Intersect with tile + FloatRect tileBounds = this->tileBounds(tile); + FloatRect srcRectIntersected = srcRect; + srcRectIntersected.intersect(tileBounds); + + if (srcRectIntersected.isEmpty()) { + *newSrc = *newDst = FloatRect(0, 0, 0, 0); + return; + } + + float srcRectIntersectedNormX = (srcRectIntersected.x() - srcRect.x()) / srcRect.width(); + float srcRectIntersectedNormY = (srcRectIntersected.y() - srcRect.y()) / srcRect.height(); + float srcRectIntersectedNormW = srcRectIntersected.width() / srcRect.width(); + float srcRectIntersectedNormH = srcRectIntersected.height() / srcRect.height(); + + *newSrc = srcRectIntersected; + newSrc->move( + -tileBounds.x() + ((tileXIndex(tile) > 0) ? m_borderTexels : 0), + -tileBounds.y() + ((tileYIndex(tile) > 0) ? m_borderTexels : 0)); + + *newDst = FloatRect( + srcRectIntersectedNormX * dstRect.width() + dstRect.x(), + srcRectIntersectedNormY * dstRect.height() + dstRect.y(), + srcRectIntersectedNormW * dstRect.width(), + srcRectIntersectedNormH * dstRect.height()); +} + +} diff --git a/WebCore/platform/graphics/chromium/TilingData.h b/WebCore/platform/graphics/chromium/TilingData.h new file mode 100755 index 0000000..f12e66e --- /dev/null +++ b/WebCore/platform/graphics/chromium/TilingData.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TilingData_h +#define TilingData_h + +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class FloatRect; +class IntRect; + +class TilingData : public Noncopyable { +public: + TilingData(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels); + int maxTextureSize() const { return m_maxTextureSize; } + int totalSizeX() const { return m_totalSizeX; } + int totalSizeY() const { return m_totalSizeY; } + + int numTiles() const { return numTilesX() * numTilesY(); } + int numTilesX() const { return m_numTilesX; } + int numTilesY() const { return m_numTilesY; } + int tileIndex(int x, int y) const { return x + y * numTilesX(); } + int tileXIndex(int tile) const { assertTile(tile); return tile % numTilesX(); } + int tileYIndex(int tile) const { assertTile(tile); return tile / numTilesX(); } + int tileXIndexFromSrcCoord(int) const; + int tileYIndexFromSrcCoord(int) const; + + IntRect tileBounds(int tile) const; + IntRect tileBoundsWithBorder(int tile) const; + FloatRect tileBoundsNormalized(int tile) const; + int tilePositionX(int xIndex) const; + int tilePositionY(int yIndex) const; + int tileSizeX(int xIndex) const; + int tileSizeY(int yIndex) const; + IntRect overlappedTileIndices(const IntRect& srcRect) const; + IntRect overlappedTileIndices(const FloatRect& srcRect) const; + + // Given a set of source and destination coordinates for a drawing quad + // in texel units, returns adjusted data to render just the one tile. + void intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile, FloatRect* newSrc, FloatRect* newDst) const; + +private: + TilingData() : m_maxTextureSize(0), m_totalSizeX(0), m_totalSizeY(0) {} + void assertTile(int tile) const { ASSERT(tile >= 0 && tile < numTiles()); } + + int m_maxTextureSize; + int m_totalSizeX; + int m_totalSizeY; + int m_borderTexels; // 0 or 1 + + // computed values: + int m_numTilesX; + int m_numTilesY; +}; + +} + +#endif // TilingData_h |