void TextObjectImp::draw(double zoomFactor) const { RectangleObjectImp::draw(zoomFactor); if (QGLContext::currentContext() != mpDrawContext || mUpdateTexture == true) { (const_cast<TextObjectImp*> (this))->updateTexture(); } if (mpDrawContext == NULL) { return; } LocationType llCorner = getLlCorner(); LocationType urCorner = getUrCorner(); glEnable(GL_TEXTURE_2D); // switch to using this tile's texture GLuint textureId = mTextureResource; if (mpDrawContext == mTempTextureResource.getContext()) { textureId = mTempTextureResource; } glBindTexture(GL_TEXTURE_2D, textureId); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); double maxS = mDataWidth / static_cast<double>(mTextureWidth); double maxT = mDataHeight / static_cast<double>(mTextureHeight); ColorType color = getTextColor(); glBegin(GL_QUADS); glColor4ub(color.mRed, color.mGreen, color.mBlue, 255); // Determine if the bounding box is flipped based on its screen locations bool bHorizontalFlip = false; bool bVerticalFlip = false; GraphicLayer* pLayer = getLayer(); if (pLayer != NULL) { pLayer->isFlipped(llCorner, urCorner, bHorizontalFlip, bVerticalFlip); // Account for the difference between screen origin (upper left) and OpenGL origin (lower left) bVerticalFlip = !bVerticalFlip; } // Draw the text left to right and right side up if ((bHorizontalFlip == false) && (bVerticalFlip == false)) { glTexCoord2f(0.0, 0.0); glVertex3f(llCorner.mX, llCorner.mY, 0.0); glTexCoord2f(maxS, 0.0); glVertex3f(urCorner.mX, llCorner.mY, 0.0); glTexCoord2f(maxS, maxT); glVertex3f(urCorner.mX, urCorner.mY, 0.0); glTexCoord2f(0.0, maxT); glVertex3f(llCorner.mX, urCorner.mY, 0.0); } else if ((bHorizontalFlip == true) && (bVerticalFlip == false)) { glTexCoord2f(maxS, 0.0); glVertex3f(llCorner.mX, llCorner.mY, 0.0); glTexCoord2f(0.0, 0.0); glVertex3f(urCorner.mX, llCorner.mY, 0.0); glTexCoord2f(0.0, maxT); glVertex3f(urCorner.mX, urCorner.mY, 0.0); glTexCoord2f(maxS, maxT); glVertex3f(llCorner.mX, urCorner.mY, 0.0); } else if ((bHorizontalFlip == true) && (bVerticalFlip == true)) { glTexCoord2f(maxS, maxT); glVertex3f(llCorner.mX, llCorner.mY, 0.0); glTexCoord2f(0.0, maxT); glVertex3f(urCorner.mX, llCorner.mY, 0.0); glTexCoord2f(0.0, 0.0); glVertex3f(urCorner.mX, urCorner.mY, 0.0); glTexCoord2f(maxS, 0.0); glVertex3f(llCorner.mX, urCorner.mY, 0.0); } else if ((bHorizontalFlip == false) && (bVerticalFlip == true)) { glTexCoord2f(0.0, maxT); glVertex3f(llCorner.mX, llCorner.mY, 0.0); glTexCoord2f(maxS, maxT); glVertex3f(urCorner.mX, llCorner.mY, 0.0); glTexCoord2f(maxS, 0.0); glVertex3f(urCorner.mX, urCorner.mY, 0.0); glTexCoord2f(0.0, 0.0); glVertex3f(llCorner.mX, urCorner.mY, 0.0); } glEnd(); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // mTempTextureResource is allocated by the updateTexture method when the gl context has changed // Free the texture here; more importantly set mpDrawContext to mTextureResource so that the next // draw operation completes successfully without the need to recreate the texture. if (mTempTextureResource.get() != NULL) { TextObjectImp* pNonConst = const_cast<TextObjectImp*>(this); pNonConst->mTempTextureResource = GlTextureResource(0); pNonConst->mpDrawContext = mTextureResource.getContext(); } }
void ScaleBarObjectImp::updateLayout() { if (mNeedsLayout == false) { return; } LocationType llCorner = getLlCorner(); LocationType urCorner = getUrCorner(); bool bHorizontalFlip = false; bool bVerticalFlip = false; GraphicLayer* pLayer = getLayer(); if (pLayer != NULL) { pLayer->isFlipped(llCorner, urCorner, bHorizontalFlip, bVerticalFlip); } if (bHorizontalFlip == true) { double temp = llCorner.mX; llCorner.mX = urCorner.mX; urCorner.mX = temp; } if (bVerticalFlip == true) { double temp = llCorner.mY; llCorner.mY = urCorner.mY; urCorner.mY = temp; } double barHeight = urCorner.mY - llCorner.mY; double spacingScale = 1.0; string unitsText = "pix"; double unitScale = 1.0; //mXgsd is calculated in meters if (mpGeoreference.get() != NULL) { if (getUnitSystem() == UNIT_KFT) { unitsText = "ft"; } else if (getUnitSystem() == UNIT_KM) { unitsText = "m"; } else if (getUnitSystem() == UNIT_MI) { unitsText = "mi"; } // if the scalebar is an object in the layout layer, we need to scale the // scalebar length to scene pixels from page coordinates if (getUnitSystem() == UNIT_KFT) { unitScale = GeoConversions::convertMetersToFeet(1); } else if (getUnitSystem() == UNIT_MI) { unitScale = GeoConversions::convertMetersToMiles(1); } } else { mXgsd = 1.0; } double deltaX = urCorner.mX - llCorner.mX; double lengthBar = fabs(deltaX * mXgsd * unitScale); double totalLengthPixels = fabs(deltaX); double ticksize = 0.0; //ticksize in pixels double ticksizeDistance = pow(10.0, floor(log10(lengthBar / 5.0))); //ticksize in specific units (feet or meters) if (ticksizeDistance * 5.0 * 5.0 > lengthBar) { if (ticksizeDistance * 2.0 * 5.0 > lengthBar) { // times 1.0; } else { ticksizeDistance *= 2.0; } } else { ticksizeDistance *= 5.0; } if (mpGeoreference.get() == NULL || getUnitSystem() == UNIT_KM || getUnitSystem() == UNIT_KFT) { if (ticksizeDistance >= (1000 / 5.0)) // 5 ticks >= 1000 base units (either meters or feet) { spacingScale /= 1000.0; //meters to kilometers, feet to kilofeet unitsText = "k" + unitsText; } } else if (getUnitSystem() == UNIT_MI) { if (ticksizeDistance < (0.25 / 5.0)) //5 ticks is less than 1/4 mile, convert to feet. { spacingScale = GeoConversions::convertMilesToFeet(spacingScale); unitsText = "ft"; } } // need to divide ticksize by gsd here if (lengthBar != 0.0) { ticksize = DrawUtil::sign(deltaX) * ticksizeDistance * totalLengthPixels / lengthBar; // ticksize in pixels } ostringstream center; center << (ticksizeDistance * 5.0) * spacingScale << unitsText; TextStringProperty centerText(center.str()); ostringstream right; right << lengthBar * spacingScale << unitsText; string newRightVal = right.str(); TextStringProperty rightText(right.str()); TextStringProperty leftText("0" + unitsText); double width = 0.0; double height = 0.0; int i = 0; list<GraphicObject*> objects = mpGroup->getObjects(); list<GraphicObject*>::iterator it = objects.begin(); for (i = 0; it != objects.end(); ++it, ++i) { GraphicObjectImp* pObj = dynamic_cast<GraphicObjectImp*>(*it); TextObjectImp* pText = NULL; if (pObj == NULL) { continue; } LocationType llObjCorner = pObj->getLlCorner(); LocationType urObjCorner = pObj->getUrCorner(); switch (i) { case 0: // big, stretchy rectangle llObjCorner.mX = llCorner.mX; urObjCorner.mX = urCorner.mX; llObjCorner.mY = llCorner.mY + barHeight * (1.0-BOX_HEIGHT); urObjCorner.mY = llObjCorner.mY + barHeight * BOX_HEIGHT; pObj->setBoundingBox(llObjCorner, urObjCorner); pObj->updateHandles(); break; case 1: case 2: case 3: case 4: case 5: // 5 rectangles llObjCorner.mX = ((i-1) * ticksize) + llCorner.mX; urObjCorner.mX = (i * ticksize) + llCorner.mX; llObjCorner.mY = llCorner.mY + barHeight * (1.0-BOX_HEIGHT); urObjCorner.mY = llObjCorner.mY + barHeight * BOX_HEIGHT; pObj->setBoundingBox(llObjCorner, urObjCorner); pObj->updateHandles(); break; case 6: //center line llObjCorner.mX = (5.0 * ticksize) + llCorner.mX; urObjCorner.mX = llObjCorner.mX; llObjCorner.mY = llCorner.mY + barHeight * (1.0-BOX_HEIGHT - CENTER_LINE_HEIGHT); urObjCorner.mY = llObjCorner.mY + barHeight * CENTER_LINE_HEIGHT; pObj->setBoundingBox(llObjCorner, urObjCorner); pObj->updateHandles(); break; case 7: // left line llObjCorner.mX = llCorner.mX; urObjCorner.mX = llCorner.mX; llObjCorner.mY = llCorner.mY + barHeight * TEXT_HEIGHT; urObjCorner.mY = llObjCorner.mY + barHeight * LINE_HEIGHT; pObj->setBoundingBox(llObjCorner, urObjCorner); pObj->updateHandles(); break; case 8: //right line llObjCorner.mX = urCorner.mX; urObjCorner.mX = llObjCorner.mX; llObjCorner.mY = llCorner.mY + barHeight * TEXT_HEIGHT; urObjCorner.mY = llObjCorner.mY + barHeight * LINE_HEIGHT; pObj->setBoundingBox(llObjCorner, urObjCorner); pObj->updateHandles(); break; case 9: { //left text pText = dynamic_cast<TextObjectImp*>(pObj); VERIFYNRV(pText != NULL); if (pObj->getText() != leftText.getString()) { pText->setProperty(&leftText); pText->updateTexture(); } else { pText->updateBoundingBox(); } LocationType textLlCorner = pText->getLlCorner(); LocationType textUrCorner = pText->getUrCorner(); width = textUrCorner.mX - textLlCorner.mX; height = textUrCorner.mY - textLlCorner.mY; llObjCorner.mX = llCorner.mX; llObjCorner.mY = llCorner.mY; if (height != 0.0) { urObjCorner.mX = llObjCorner.mX + width * barHeight * TEXT_HEIGHT / height; } else { urObjCorner.mX = llObjCorner.mX + width; } urObjCorner.mY = llObjCorner.mY + barHeight * TEXT_HEIGHT; pObj->setBoundingBox(llObjCorner, urObjCorner); break; } case 10: { //center text pText = dynamic_cast<TextObjectImp*>(pObj); VERIFYNRV(pText != NULL); if (pObj->getText() != centerText.getString()) { pText->setProperty(¢erText); pText->updateTexture(); } else { pText->updateBoundingBox(); } LocationType textLlCorner = pText->getLlCorner(); LocationType textUrCorner = pText->getUrCorner(); width = textUrCorner.mX - textLlCorner.mX; height = textUrCorner.mY - textLlCorner.mY; if (height != 0.0) { llObjCorner.mX = llCorner.mX + (5.0 * ticksize) - (width / 2.0) * barHeight * TEXT_HEIGHT / height; urObjCorner.mX = llObjCorner.mX + width * barHeight * TEXT_HEIGHT / height; } else { llObjCorner.mX = llCorner.mX + (5.0 * ticksize); urObjCorner.mX = llObjCorner.mX + width; } llObjCorner.mY = llCorner.mY + (1.0-BOX_HEIGHT-TEXT_HEIGHT-CENTER_LINE_HEIGHT)*barHeight; urObjCorner.mY = llObjCorner.mY + barHeight*TEXT_HEIGHT; pObj->setBoundingBox(llObjCorner, urObjCorner); break; } case 11: { //right text pText = dynamic_cast<TextObjectImp*>(pObj); VERIFYNRV(pText != NULL); if (pObj->getText() != rightText.getString()) { pText->setProperty(&rightText); pText->updateTexture(); } else { pText->updateBoundingBox(); } LocationType textLlCorner = pText->getLlCorner(); LocationType textUrCorner = pText->getUrCorner(); width = textUrCorner.mX - textLlCorner.mX; height = textUrCorner.mY - textLlCorner.mY; if (height != 0.0) { llObjCorner.mX = urCorner.mX - width * barHeight * TEXT_HEIGHT / height; urObjCorner.mX = llObjCorner.mX + width * barHeight * TEXT_HEIGHT / height; } else { llObjCorner.mX = urCorner.mX; urObjCorner.mX = llObjCorner.mX + width; } llObjCorner.mY = llCorner.mY; urObjCorner.mY = llObjCorner.mY + barHeight*TEXT_HEIGHT; pObj->setBoundingBox(llObjCorner, urObjCorner); break; } default: break; } } mpGroup->updateBoundingBox(); mNeedsLayout = false; }